java - for-each循环中的变量副本?
问题描述
我的印象是 for-each 循环中的变量会从数组的元素中复制值。例如:
String[] strs = new String[] {"a", "b"};
for (String s : strs) {
s = "c";
}
for (String s : strs) {
System.out.println(s);
}
上面的代码与原始数组 strs 无关,因此输出仍然是:
a
b
这是预期的,因为 for-each 循环中的变量 s 实际上是元素的副本。但是,如果我定义自己的类以及赋值构造函数,行为会发生变化:
class Node {
public Node(Integer value, String str) {
value_ = new Integer(value.intValue());
str_ = new String(str.toCharArray());
}
public Node(Node node) {
this(node.value(), node.str());
}
public Integer value() { return value_; }
public String str() { return str_; }
public Integer value_ = 0;
public String str_ = "null";
}
Node[] my_list = new Node[] {new Node(1, "a"), new Node(2, "b")};
for (Node n : my_list) {
n.value_ = 3;
n.str_ = "c";
}
for (Node n : my_list) {
System.out.println(n.value() + " " + n.str());
}
现在的输出是:
3 c
3 c
这意味着 for-each 循环中的变量 n 不是元素的副本,而是引用。
任何人都可以帮助解释为什么 for-each 循环在 String 和我自己的类 Node 上的行为不一致?
谢谢!
解决方案
for-each 循环中的变量值是您正在迭代的值的副本。
请记住,Java 有两种类型的值:原始值和引用值。引用值是指向对象的指针。
在第一个示例中,s = "c"
使变量s
指向一个新对象。由于s
是循环内的局部变量,因此您无法从外部观察到任何效果。
在第二个例子中,n.value_ = 3
首先找到n
指向的对象:记住这n
是一个引用值,它是一个指向对象的指针。然后它会改变该value_
对象中字段的值。这些对象存在于循环之外,因此可以从外部看到这种变化。
另请参阅关于引用与值语义如何影响传递给方法的值的非常类似的讨论,Java 是“按引用传递”还是“按值传递”?
推荐阅读
- json - 异常:FormatException:意外字符(在字符 1 处)
- linear-programming - 在 SCIP 优化软件中释放 SCIP_SOL* 和 SCIP*
- python - 使用 L2 距离差异进行面部识别
- mysql - 仅获取某些值 (sql)
- ruby - Bundler v2.0.2 拒绝在 Mac OS Catalina 上安装 libxml-ruby 3.1.0
- javascript - 如何让 Discord 机器人从 DM 中删除自己的消息?(不和谐.js)
- http - 如何在不派生的情况下复制上下文对象
- google-apps-script - 谷歌图表 - 隐藏系列标签太宽
- delphi - 如何在 Delphi/Firemonkey 中破坏 ITask
- environment-variables - 属性类型“Int”与其包装器类型“EnvironmentObject”的“wrappedValue”属性不匹配