首页 > 解决方案 > 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 上的行为不一致?

谢谢!

标签: javafor-loop

解决方案


for-each 循环中的变量值是您正在迭代的值的副本。

请记住,Java 有两种类型的值:原始值和引用值。引用值是指向对象的指针。

在第一个示例中,s = "c"使变量s指向一个新对象。由于s是循环内的局部变量,因此您无法从外部观察到任何效果。

在第二个例子中,n.value_ = 3首先找到n指向的对象:记住这n是一个引用值,它是一个指向对象的指针。然后它会改变该value_对象中字段的值。这些对象存在于循环之外,因此可以从外部看到这种变化。

另请参阅关于引用与值语义如何影响传递给方法的值的非常类似的讨论,Java 是“按引用传递”还是“按值传递”?


推荐阅读