Junilu Lacar wrote:Because the instance of B is not yet fully initialized when you execute the code in the A constructor. Since that constructor makes a polymorphic call to the print() method, the value that print() picks up is the default value 0. This illustrates why you should avoid calling non-final instance methods from a constructor of a non-final class, because this sort of thing can happen.
Edit: By "polymorphic call" I mean the method that's actually called from the A constructor is B.print(), not A.print().
The instance method is polymorphic; it is therefore the B version which is called from the constructor. That shows why all methods called from the constructor should be marked private or final (no need to use both).
Ioanna Katsanou wrote:. . . A a = new B(); //This outputs 0 !! Why??? Shouldn't it output A??
. . .
The full details are to be found in the Java® Language Specification (but that can be difficult to read). You create the superclass object first (=Object), then the subclass object (=A), before the B class is instantiated. So the print() method, called from the constructor, runs before the initialisation i = 4; is completed. As Junilu says, the B object is still incompletely constructed and is in an inconsistent state; i is still 0. Later calls to that method find the initialised value (4).
Ioanna Katsanou wrote:. . . first the instance variables and instance blocks and then the code inside the construcor is executed. Isn't that correct?
But the declaration and initialisation are in a different class; they have no existence in A.
Ioanna Katsanou wrote:. . . The constructor runs after all fields and instance initializer blocks have run.
Piet Souris wrote:My reasoning was exactly like yours: first B's i is initialized before any constructor is called
That is because static declarations and initialisations and static initialiser blocks are executed when the class is loaded and instance code is not executed until the object is created.
Piet Souris wrote: . . . Now, changing BB's i to a static variable, will give 4 and not 0. . . .
What default constructor? You don't have any default constructors. You have non‑empty no‑arguments constructors which you wrote, but those are different from default constructors. It's all in the JLS. So is the fact that the compiler adds an implicit super(); constructor invocation to every constructor which hasn't already got an explicit super(...); or this(...); written. So when you enter the constructor, you go immediately to the superclass, so you start off by initialising an instance of Object before any of A is initialised. Then you initialise A before any of B, etc.
Piet Souris wrote:. . . why the default constructor begins with a call to super(), since that has already taken place. . . .
Piet, you probably mean 'B' (OP's version), rather than 'BB' (yours version). Yours version has explicit constructor, OP's not.
Piet Souris wrote:Since BB has no explicit constructor, it gets a default constructor that starts with super(). Is that incorrect?
But tell me: would you have answered this question correctly?
I would have realised it would print a number not "A" but would probably have expected 4.
Piet Souris wrote:. . . would you have answered this question correctly?
We all make mistakes; think nothing of it. It is a good thing to be able to admit to mistakes.
Piet Souris wrote:. . . Sorry, I will humbly shut up now.
Campbell Ritchie wrote:That is because static declarations and initialisations and static initialiser blocks are executed when the class is loaded and instance code is not executed until the object is created.
Piet Souris wrote:BB inherits from AA. In order for BB to inherit all properties, AA needs to be known in advance and in full, so, AA class first gets constructed in full
Because the declaration mentions both AA and BB, both classes are loaded. Also Class<AA> and Class<BB> objects are created. If there is no mention of the superclass, I don't know whether it is loaded or not. You can test that easily with a static initialiser containing a print statement.
Ioanna Katsanou wrote:. . . BB inherits from AA.
Does that mean that both classes are loaded at this point?? Or only BB is loaded?
The class is not constructed. An object is constructed, of B, but part of that object is specified by class A, so that part is constructed first.
. . . A class first gets constructed in full . . .
I think you have apart from what I said earlier in this post. Have a look at the JLS section which I linked to yesterday. That has all the details in.
. . . Have I gotten it right or not :P ?
And that is because AA is a base class of BB.
Dave Tolls wrote:I'm fairly sure, AA being loaded first.