• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Super constructor + instance methods/variables (K&B)

 
Paolo Dina
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Good day all. At page 130 the book says: "You cannot make a call to an instance method or access an instance variable, until after the super constructor runs.".

Given that super and this are mutually exclusive inside the same constructor, and when one of them appears, it has to be before everything else, I'm wondering how it'd be possible to call an instance method or access an instance variable *before* super constructor has ran and terminated. Would instead be possible to do a println? I don't think so.

Probably I have misinterpreted the sentence on the book, in this case any code example to clarify is appreciated.

Thanks
 
Ankit Garg
Sheriff
Posts: 9528
33
Android Google Web Toolkit Hibernate IntelliJ IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Paolo welcome to javaranch.

I also wondered about that some time ago. Here's an example of accessing instance field before super call

 
Paolo Dina
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ah.

Thanks for the prompt reply!
 
Harvinder Thakur
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Paolo

The example given by Ankit is perfect.

I would just like to highlight another aspect of how the jvm behaves when accessing instance methods before the super constructor has finished execution.

Just have a look at the following code sample taken from JLS:




produces the output:


0
3


The explanation given is as follows:

If methods are invoked that are overridden in subclasses in the object being initialized, then these overriding methods are used, even before the new object is completely initialized. This shows that the invocation of printThree in the constructor for class Super does not invoke the definition of printThree in class Super, but rather invokes the overriding definition of printThree in class Test. This method therefore runs before the field initializers of Test have been executed, which is why the first value output is 0, the default value to which the field three of Test is initialized. The later invocation of printThree in method main invokes the same definition of printThree, but by that point the initializer for instance variable three has been executed, and so the value 3 is printed.
 
Ankit Garg
Sheriff
Posts: 9528
33
Android Google Web Toolkit Hibernate IntelliJ IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Harvindar you are right. You can use instance methods from the super class. The rule is that you cannot call instance fields and methods before the super constructor get's called. After the super constructor is called, it can use instance methods from the sub-class...
 
Harvinder Thakur
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ankit.... it's *Harvinder* and not *Harvindar*
 
Ankit Garg
Sheriff
Posts: 9528
33
Android Google Web Toolkit Hibernate IntelliJ IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oops! Sorry Harvinder
 
Mukta tripathi
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello xperts,

I did not understand how it is printing 0, could someone please xplain me that.

thank a ton
 
Paolo Dina
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm not an xpert but I'll try to help anyway. Please correct me if my explanation is wrong, thanks.

In the snippet of code, consider: the superclass called Super, the subclass called Test and the printThree() in Test (which is a legal override of printThree() in Super.).

When you run "java Test" happens that the main() method inside Test is called and a new object of type Test starts his life in this way:

1. Test() constructor is invoked

This is the code for default constructor Test() that the compiler implicitly provides even if you don't type it:

2. Superclass' no-args constructor first implicitly invokes Object's default constructor, and this has no "visible" effects, then invokes printThree() method. As printThree() has been overridden, it is important to note that (as JLS says) the code:


is *not* executed. Instead the version that will be invoked is the one in Test class (JLS says that).

This ends the preamble. JLS should now be more clear:


If methods are invoked that are overridden in subclasses in the object being initialized, then these overriding methods are used, even before the new object is completely initialized. This shows that the invocation of printThree in the constructor for class Super does not invoke the definition of printThree in class Super, but rather invokes the overriding definition of printThree in class Test. This method therefore runs before the field initializers of Test have been executed, which is why the first value output is 0, the default value to which the field three of Test is initialized.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic