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:
- Can
thisbe used initializing instance variables? - Should it be done?
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:
- Allocates memory for all the instance variables of this class and all its superclasses.
- Initializes all the variables with default values
- "Properly" initializes all the variables in textual order starting from its highest superclasses (i.e. Object) and finishing with this class - so
secondis initialized (i.e. constructed) prior to i being initialized to 3. - If any of these "proper" initializations call another method or another constructor, this is done before the first constructor is invoked - so
secondis constructed and returned prior to theFirstClassconstructor being run. - If another constructor is invoked by instance initialization (such as in item 4), it goes through the same process from item 1 (memory allocation, initialization etc)
The reason doing this is bad is that the 'guaranteed' result can change in two ways:
- If the source code order is changed (e.g. if
iis initialized beforesecondis constructed) the result will change. It would be easy not to notice this. - If someone subclasses our class (or classes), they may not be aware of the delicate balance and could change something that affects the result when overwriting.
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.