Reputation: 589
Before Marking this as duplicate please read the question once. I have read the question related to this
from here already.
I have two java class Test2 and Test as given below. As far as I understand this
refers to current object and can be used inside constructors
, non-static methods
and various other places as given in other question (link given above). But when I am initialising the instance variable in Test2 using this
:
Hello World!
?Class Test2.java
public class Test2 {
private String test2Str;
private Test test = new Test(this);//Please notice the instance variable init
public Test2(String str){
this.test2Str = str;
}
public Test getTest() {
return test;
}
public String getStr() {
return this.test2Str;
}
public void setTest(Test test) {
this.test = test;
}
public static void main(String[] args){
Test2 object = new Test2("Hello World!");
String thisStr = object.getTest().getStr();
System.out.println(thisStr);
}
}
Class Test.java
public class Test {
String str;
public Test(Test2 test){
System.out.println(test);
System.out.println(test.getStr());
str = test.getStr();
}
public void setStr(String str){
this.str = str;
}
public String getStr(){
return this.str;
}
}
First Output of the program :
com.avnet.spoj.lifeuniverse.Test2@56e5b723
null
null
Note : If I move instance variable initialisation inside constructor as given below. It works as expected and I can understand that. Can somebody explain above behaviour of this
?
private String test2Str;
private Test test = null;
public Test2(String str){
this.test2Str = str;
test = new Test(this);
}
Second Output of the program :
com.avnet.spoj.lifeuniverse.Test2@56e5b723
Hello World!
Hello World!
Upvotes: 0
Views: 49
Reputation: 3529
From this answers https://stackoverflow.com/a/4916805/4886927 :
Initialisers are executed before constructor bodies. (Which has implications if you have both initialisers and constructors, the constructor code executes second and overrides an initialised value).
Upvotes: 1
Reputation: 13133
this
refers to the 'current instance' of the class in which it appears, but using it as your first example does during initialization is partially undefined. That code runs before the constructor runs; anything that refers to the instance of the variable before the constructor is completed has to be regarded as suspicious. This is, at the least, poor coding practice.
Upvotes: 0
Reputation: 691913
The code in your first snippet:
private String test2Str;
private Test test = new Test(this);//Please notice the instance variable init
public Test2(String str){
this.test2Str = str;
}
is equivalent to
private String test2Str = null;
private Test test = null;
public Test2(String str){
test = new Test(this);
this.test2Str = str;
}
So, when new Test(this)
is invoked, this
is the Test2 instance being constructed, but at the time it's called, this.test2Str = str
has not been executed yet, and is test2Str
is thus null. That's why you see
null
null
being printed.
In your second example, new Test(this)
is called after this.test2Str = str
has been executed, and that's why you see
Hello World!
Hello World!
being printed.
You should really avoid leaking this
to external objects, or even to overridable methods, from a constructor: these external objects will see a partially constructed object, which will thus not respect its invariants.
Upvotes: 3