Win a 3 month subscription to Marco Behler Videos this week in the Spring forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Inheritance Question  RSS feed

 
Ioanna Katsanou
Ranch Hand
Posts: 111
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,

I encountered this question in Enthuware:
I read the explanation in enthuware forum but stil I cannot understand the answer !


Thanks in advance
 
Junilu Lacar
Sheriff
Posts: 10929
158
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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().
 
Ioanna Katsanou
Ranch Hand
Posts: 111
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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().


Yes but, I thought that the order of initalization when "new" is called, first the instance variables and instance blocks and then the code inside the construcor is executed. Isn't that correct?
 
Campbell Ritchie
Marshal
Posts: 54909
155
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ioanna Katsanou wrote:. . . A a = new B();       //This outputs 0 !! Why??? Shouldn't it output A??
. . .
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 shou‍ld be marked private or final (no need to use both).
 
Ioanna Katsanou
Ranch Hand
Posts: 111
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I though that when writing "new" according to the order of initialization:

Instance Fields and instance initializer blocks are run in the order in which they appear in
the file.
The constructor runs after all fields and instance initializer blocks have run.

 
Campbell Ritchie
Marshal
Posts: 54909
155
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ioanna Katsanou wrote:. . . first the instance variables and instance blocks and then the code inside the construcor is executed. Isn't that correct?
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).
 
Campbell Ritchie
Marshal
Posts: 54909
155
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ioanna Katsanou wrote:. . . The constructor runs after all fields and instance initializer blocks have run.
But the declaration and initialisation are in a different class; they have no existence in A.
 
Piet Souris
Rancher
Posts: 1916
66
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Ioanna

don't worry, I did not (and still don't) understand the answer as well. My reasoning was exactly like yours: first B's i is initialized before any constructor is called (that would be the default constructor, with a call to A()). And so i should have been known at that stage. However, running the program, we must acknowlegde that the explanation is, somehow, correct.
So I added some initializers to the code, to see in what sequence the code is being executed. And indeed, A() is called at first. So, try this:
//================================================================

and the outcome is:
In AA, initializer...
In AA's constructor...
This is BB's print method: 0
In BB's initializer; i = 4
In BB's constructor, i = 4
This is BB's print method: 4


Draw your own conclusions.
Now, changing BB's i to a static variable, will give 4 and not 0.

Well, this is all beyond me, so let's hope we won't get such questions on the exam...
Burt kudo's to those people of Enthuware... just when you thought you knew it all, they put you firmly with both feet on the ground again. For a tenner (ex vat) that is money very well spent.
 
Liutauras Vilda
Marshal
Posts: 4271
256
BSD
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Piet Souris wrote:My reasoning was exactly like yours: first B's i is initialized before any constructor is called

I might will not be correct in used terminology nor I'll be super precise, but it might helps to think and explains all that mess next simplification:

B inherits from A. In order for B to inherit all properties, A needs to be known in advance and in full, so, A class first gets constructed in full, B is waiting, and since again polymorphic method is part of A constructor, it does what it does, using only partially known B properties when the class was loaded, but not ran yet, as all construction happens at run time, not compile or class load time.
 
Piet Souris
Rancher
Posts: 1916
66
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks.

But my output shows that AA's constructor is being invoked even before BB's initializer. That makes me wonder why the default constructor begins with a call to super(), since that has already taken place.

It is typically one of those questions that you get correct, but only if you know the correct answer...

But it is only a worry for the OCAJP... after that I'll have my IDE to take care of these nice details     
 
Campbell Ritchie
Marshal
Posts: 54909
155
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Piet Souris wrote: . . . Now, changing BB's i to a static variable, will give 4 and not 0. . . .
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.
Look at the Java® Language Specification page I showed you earlier; that explain exactly which order the different parts are executed in.
 
Campbell Ritchie
Marshal
Posts: 54909
155
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Piet Souris wrote:. . . why the default constructor begins with a call to super(), since that has already taken place. . . .
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
Rancher
Posts: 1916
66
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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?
 
Liutauras Vilda
Marshal
Posts: 4271
256
BSD
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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?
Piet, you probably mean 'B' (OP's version), rather than 'BB' (yours version). Yours version has explicit constructor, OP's not.
 
Piet Souris
Rancher
Posts: 1916
66
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Arrgghh.... you are right, this is a version I made to see if an explicit constructor would make any difference (which it didn't). I understand Campbell's reaction now. Hmmm... I seem to be making a mess out of this topic. Sorry, I will humbly shut up now.
 
Campbell Ritchie
Marshal
Posts: 54909
155
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Piet Souris wrote:. . . would you have answered this question correctly?
I would have realised it would print a number not "A" but would probably have expected 4.
 
Campbell Ritchie
Marshal
Posts: 54909
155
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Piet Souris wrote:. . . Sorry, I will humbly shut up now.
We all make mistakes; think nothing of it. It is a good thing to be able to admit to mistakes.
Apology accepted
 
Ioanna Katsanou
Ranch Hand
Posts: 111
1
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.


Ok so just to set things straight..



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



BB inherits from AA.
Does that mean that both classes are loaded at this point?? Or only BB is loaded?
If both classes are loaded at this point then  then first all the static fields/initializer blocks of Class AA should run and then all the static fields/initializer blocks of Class BB should run at this point.
If only BB loads then only the static fields/initializer blocks of Class BB should run at this point, hence setting int i =4; if i was static.

Then
In order for B to inherit all properties, A needs to be known in advance and in full, so, A class first gets constructed in full so now we create the BB object.

So first we construct AA class.
So first the instance initilizers/fields run in the order they appear in the class, and then the A constructor runs.
So the output would be:
In AA, initializer...
In AA's constructor...

But AA's constructor, because of Polymorphism calls subclass's print method. (BB)
BB has not yet been constructed, so the instance initializers/field have not yet ran.
So it prints:
This is BB's print method: 0

After class's AA construction is finished, subclass BB construction starts.
So first the instance initilizers/fields run in the order they appear in the class, and then the BB constructor runs.
In BB's initializer; i = 4
In BB's constructor, i = 4


BB's constructor calls BB's print method.
This is BB's print method: 4

Have I gotten it right or not :P ?
 
Campbell Ritchie
Marshal
Posts: 54909
155
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ioanna Katsanou wrote:. . . BB inherits from AA.
Does that mean that both classes are loaded at this point?? Or only BB is loaded?
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 te‍st that easily with a static initialiser containing a print statement.
. . . A class first gets constructed in full . . .
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.
. . . Have I gotten it right or not :P ?
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.
 
Dave Tolls
Ranch Hand
Posts: 2734
30
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The following:

will, if it is the first time the BB class has been mentioned, result in both AA and BB being loaded with, I'm fairly sure, AA being loaded first.
 
Liutauras Vilda
Marshal
Posts: 4271
256
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dave Tolls wrote:I'm fairly sure, AA being loaded first.
And that is because AA is a base class of BB.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!