这是一道考试题。幸运的是我选择了正确的答案,但我仍然不明白为什么它是正确的。
考虑这个程序:
class D {
protected C c;
public D(C c) {
this.c = new C(c);
}
public C getC() {
return c;
}
public void setC(C c) {
this.c = c;
}
}
class C {
protected String s;
public C(String s) {
this.s = s;
}
public C(C c) {
this(c.s);
}
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
public static void main(String[] args) {
C c1 = new C("1");
C c2 = new C("2");
D[] d = {
new D(c1), new D(c1), new D(c2), new D(c2)
};
d[0] = d[3];
c1.setS("3");
String r = "";
for (D i: d) {
r += i.getC().getS();
}
System.out.println(r);
}
}
它将打印2122
。然而,我期望 2322
(当你运行代码时我显然是错误的)。我的理由是:
在 main 方法的第三行中,初始化了 D
的四个实例。
D
的构造函数创建一个 C
的新实例。 C
的实例有一个 String
变量,它指向内存中的某个位置。现在,d[1]
中对象的实例变量 c
(我们称之为 c3
)有一个实例变量(类型为 String
),我们称之为s3
,指向与String s1
相同的内存,变量c1
。
因此,当我们更改 s1
时,我预计 s3
的值也会更改,因为它指向内存中的同一位置。
顺便说一句,如果您更改 D
的构造函数(请参见下文),您将得到 2322
。正如我所料,因为现在 d[1]
中的变量 c3
直接指向 c1
的内存位置。
public D(C c) {
this.c = c;
}
到目前为止我对解释的想法(可能是错误的):
- 初始化实例变量
s1
/s3
时,会创建新的String
对象(到目前为止,我假设它们指向“1”
在String
池中,因为C
的构造函数使它看起来像这样) - 更改
s1
时,其指针将重定向到String
池中的“3”
。而不是“1”
在池中变成“3”
。
有人能解释一下这种行为吗?我的(错误的)推理有哪些错误?
最佳答案
这与String
池根本无关。主要回答:Is Java "pass-by-reference" or "pass-by-value"?
这是因为 D
基于 C#c
创建了 C
的新实例。这意味着 D#c
的实例与构造函数 D
中传递的参数 C
不是同一个实例,因此修改该实例不会影响 D#c
中的当前实例。
用好话重新解释这一切。
这是您正在测试的内容:
class Surprise {
String item;
public Surprise(String item) {
this.item = item;
}
//this is called copy constructor
//because you receive an object from the same class
//and copy the values of the fields into the current instance
//this way you can have a "copy" of the object sent as parameter
//and these two object references are not tied by any mean
public Surprise(Surprise another) {
//here you just copy the value of the object reference of another#item
//into this#item
this.item = another.item;
}
}
class Box {
Surprise surprise;
public Box(Surprise surprise) {
//here you create a totally new instance of Surprise
//that is not tied to the parameter surprise by any mean
this.surprise = new Surprise(surprise);
}
public static void main(String[] args) {
Surprise surprise1 = new Surprise("1");
Surprise surprise2 = new Surprise("2");
Box[] boxes = {
new Box(surprise1),
new Box(surprise1),
new Box(surprise2),
new Box(surprise2)
};
boxes[0] = boxes[3];
//you update surprise1 state
//but the state of Box#surprise in the boxes that used surprise1
//won't get affected because it is not the same object reference
surprise1.item = "3";
//print everything...
System.out.println("Boxes full of surprises");
//this code does the same as the printing above
for (Box box : boxes) {
System.out.print(box.surprise.item);
}
System.out.println();
}
}
关于java - 为什么我的变量包含 "2122"而不是 "2322"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25389506/