I've seen this
used when declaring an instance variable in IB's API, but this seems like a bad idea. Is assignment guaranteed to occur after this
has been fully constructed? Does it matter?
I thought that instance variables were initialized prior to the constructor since they can be used by the constructor. Is there some exception if this
is used?
If it somehow works, it doesn't seem like a good idea - is second
available to FirstClass
's constructor? If so, is SecondClass
constructed prior to FirstClass
? Which means that num
ends up being 3 and i
is 10? Or will there be a runtime error? Is there even any guarantee either way?
public class FirstClass {
SecondClass second = new SecondClass(this);
public int i = 3;
FirstClass(){
i = second.DoSomething();
}
}
public class SecondClass{
private int num = 10;
SecondClass(FirstClass first){
num = first.i;
}
public int DoSomething(){
return num;
}
...
}
I'd like to think that IB have a pretty solid team of developers and know what they're doing. What do you think:
this
be used initializing instance variables? EDIT
The answer is yes there is a guaranteed result (for now - but read on...), but no it shouldn't be done since its easy to inadvertently make changes to the code that could change this 'guaranteed' result.
I now know that when constructing a new object (such as FirstClass
) the JVM:
second
is initialized (ie constructed) prior to i being initialized to 3. second
is constructed and returned prior to the FirstClass
constructor being run. The reason doing this is bad is that the 'guaranteed' result can change in two ways:
i
is initialized before second
is constructed) the result will change. It would be easy not to notice this. So it looks like IB's API suffers from this delicacy, which I will have to now keep in mind.
Thanks to Emil H's answer and his direction to this article which ultimately led me to my understanding above: http://www.artima.com/designtechniques/initializationP.html - this is highly recommended reading.
Also thanks to Alexander Drobyshevsky who made a very similar point in his answer.
Sure, sometimes you have to use this, for example when a variable given through the Constructor is called as same as a instance variable:
int count;
public Test(int count){
this.count = count;
}
Yes, this
(being internally a "pointer" to the object in construction) can be used in a constructor.
A stupid example could be a self refering class
class MySelf {
Myself _me;
public MySelf() { _me = this; }
}
And there are more realistic examples. Imagine that you want a class to represent a mathematical graph, that you would initialize with a single element connected to itself.
Interesting question. What happens in the case you describe is that when you call new FirstClass()
the class loader looks up that class and loads it if its not loaded already. Then it seems to create a instance of FirstClass
where all the fields have their default values, eg second is null and i is 0.
Then it the classloader loads SecondClass
. An instance of SecondClass
is created and initialized which sets the num
field to 10. Then the constructor get's called passing in the FirstClass
instance (the fields have the values that have been initialized up to that point). So the value of num
in SecondClass
will be set to 0 in the constructor.
After the SecondClass
constructor is finished the object get's assigned to the second
field in the FirstClass
(which is still being initialized). After that i
gets initialized to 3. Now the constructor of FirstClass
get's called and i is assigned the return value of DoSomething()
which in this case will be 0.
For further reference you could look at: http://www.artima.com/designtechniques/initializationP.html It gives a description of object initalization.
TL;DR So to answere your questions:
this
can be used when initializing instance variables. this has two possible variations in Java; first, is when you wish to refer to a global variable (from an outer scope). eg:
class First {
private int x;
public void setX(int x) {
this.x = x; // outer x is equal to the parameter
}
}
another use, is to refer to the current object's constructor. eg:
public Color {
private int red, green, blue;
public void Color(int r, int g, int b) {
red = red;
green = g;
blue = b;
}
public void setColor(int r, g, b) {
this(r,g,b);
}
}
By calling this(1,2,3) with 3 parameters to tell the compiler you wish to refer to the constructor that takes 3 parameters.
Hope that helps!
At first, its a bad way to do so. You have to avoid these constructions: using not completely initialized variables. Some time it might be helpful to use "Template Method" design pattern.
Exactly for your example, in this case, result value of i = 0 after FirstClass constructor have executed; And it depends on order of assignment of i in FirstClass. If you change assignment order by next way:
public int i = 3;
SecondClass second = new SecondClass(this); // just order changed
You get answer i = 3 after FirstClass constructor have executed.
this - is only reference to current class instance. Its already exist at a time your class instance variable are beginning initializing. At first all variables have their default values (object is null, int is 0, etc.). At second are initialized all simple assignments like "int i = 3", after that executing super constructor of your current class and finally executing constructor of current class. Simple variables are initialized by order in the class up to down, BUT you should not rely on it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.