I have wired experience with reflections. At first some sample code:
public abstract class A {
public A () {
init();
}
public abstract void init ();
}
public class B extends A {
private int i = 0;
public B () {
super();
System.out.println(i);
}
public void init () {
i = 1;
}
}
Somewhere in my code I use the reflection api to instantiate an object B.
Class<AbstractSection> bc = (Class<AbstractSection>) Class.forName(B);
Constructor<?> bcon = bc.getConstructor();
B b = (B) bcon.newInstance();
What I expected was an instance of B with the variable i set to value '1'. What I got is an instance of B with i still set to '0'. With a closer look with a debugger I saw that this is not exactly correct: i is NOT still set to '0'. It is changed to '1' in the init() method and set back to '0' in the very moment when the super() call returns.
Anyone a clue? Thanks in advance,
manuel
PS: I know I can solve this by calling init() not in the super class but in the inheriting constructor.
For starters, this is nothing to do with reflection - you'd get the same results if you instantiate the class yourself.
Your confusion likely stems from the way that the i field is defined - it looks like it's set to 0 as soon as it "exists". In reality, the assignment to zero is one of the first lines of your constructor (though, crucially, after the call to super() as is required by constructors in general).
In other words, your class is exactly equivalent to the following:
public class B extends A {
private int i;
public B () {
super();
i = 0;
System.out.println(i);
}
public void init () {
i = 1;
}
}
I presume you can see now why the output is 0 instead of 1 - because the call to init() happens before the field is initialised to 0.
It is for this, and other reasons, that on the whole you should avoid calling subclass methods from a superclass constructor - since the subclass won't even have been initialised at this point, so invariants could easily be violated. (Calling methods on an unconstructed object is always a very bad idea!) That's the root cause of your problem, and the direction that you should be looking to address with a fix.
Constructors should constrain themselves to only calling methods that are private or final, for this reason. For more details, see (amongst others):
Any non-static class properties will be set to their default value in class's constructor:
boolean false
char '\u0000'
byte,short,int,long 0
float, double +0.0f or +0.0d
object null
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With