This was a question on an exam. Luckily I picked the right answer, but I still can't see why it's right.
Consider this program:
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);
}
}
It'll print 2122
. I would expect 2322
however (I'm clearly wrong when you run the code). My reasoning behind that:
In the third line of the main method, four instances of D
get initialized.
The constructor of D
makes a new instance of C
. An instance of C
has a String
variable which points somewhere to a spot in the memory. Now the instance variable c
, let's call it c3
, of the object in d[1]
has a instance variable (type String
), let's call it s3
, pointing to the same memory as the String s1
, variable of c1
.
So when we change s1
, I'd expect the value of s3
also to change, since it's pointing to the same spot in the memory.
On a side note, if you change the constructor of D
, see below, you'll get 2322
instead. Which I'd expect, since now the variable c3
in d[1]
is pointing directly towards the memory location of c1
.
public D(C c) {
this.c = c;
}
My thoughts so far on the explanation (could be wrong):
- When initializing the instance variable
s1
/s3
, newString
objects get made (so far I assumed they were pointing towards"1"
in theString
pool, since the constructor ofC
makes it look that way) - When changing
s1
, it's pointer will be redirected towards"3"
in theString
pool. Rather than"1"
becoming"3"
in the pool.
Could anyone explain this behaviour? What are the errors in my (faulty) reasoning?