jQuery in Action, 2nd edition
The moose likes Java in General and the fly likes a surprise behavior of polymorphic methods inside constructors in 《Thinking in Java》 Big Moose Saloon
  Search | Java FAQ | Recent Topics
Register / Login


Win a copy of The Mikado Method this week in the Agile and other Processes forum!
JavaRanch » Java Forums » Java » Java in General
Reply Bookmark "a surprise behavior of polymorphic methods inside constructors in 《Thinking in Java》" Watch "a surprise behavior of polymorphic methods inside constructors in 《Thinking in Java》" New topic
Author

a surprise behavior of polymorphic methods inside constructors in 《Thinking in Java》

Song Guo
Greenhorn

Joined: Apr 24, 2011
Posts: 24

the code is as follows:

the output is as follws:

Glyph constructor before draw
RoundGlyph draw, radius = 0
Glyph constructor after draw
RoundGlyph constructor, radius = 5

In the constructor of the class Glyph, when the program executes draw(), the overridden method void draw() in class RoundGlyph executes, why?? I want to know the mechanism, very thank you !
Randall Twede
Ranch Hand

Joined: Oct 21, 2000
Posts: 4092
    
    1
probably when the code is run it is this:
java RoundGlyph
the Glyph constructor gets called first because it is RoundGlyph's super
that is my guess anyway
actually that doesn't explain it either. i am curious to see what others say about this


SCJP
dennis deems
Ranch Hand

Joined: Mar 12, 2011
Posts: 808
Song Guo wrote:In the constructor of the class Glyph, when the program executes draw(), the overridden method void draw() in class RoundGlyph, why?? I want to know the mechanism, very thank you !

When draw() is called, it is called on the instance. Even though the superclass constructor is called, it is still an instance of the subclass. So the overridden subclass implementation is called.
Song Guo
Greenhorn

Joined: Apr 24, 2011
Posts: 24

Dennis Deems wrote:
Song Guo wrote:In the constructor of the class Glyph, when the program executes draw(), the overridden method void draw() in class RoundGlyph, why?? I want to know the mechanism, very thank you !

When draw() is called, it is called on the instance. Even though the superclass constructor is called, it is still an instance of the subclass. So the overridden subclass implementation is called.


But the both the classes are not fully constructed, is not it ?
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 16695
    
  19

Song Guo wrote:
Dennis Deems wrote:
Song Guo wrote:In the constructor of the class Glyph, when the program executes draw(), the overridden method void draw() in class RoundGlyph, why?? I want to know the mechanism, very thank you !

When draw() is called, it is called on the instance. Even though the superclass constructor is called, it is still an instance of the subclass. So the overridden subclass implementation is called.


But the both the classes are not fully constructed, is not it ?



Basically, method overriding rules apply, even before the object is fully initialized.

Henry


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Song Guo
Greenhorn

Joined: Apr 24, 2011
Posts: 24

Henry Wong wrote:
Song Guo wrote:
Dennis Deems wrote:
Song Guo wrote:In the constructor of the class Glyph, when the program executes draw(), the overridden method void draw() in class RoundGlyph, why?? I want to know the mechanism, very thank you !

When draw() is called, it is called on the instance. Even though the superclass constructor is called, it is still an instance of the subclass. So the overridden subclass implementation is called.


But the both the classes are not fully constructed, is not it ?



Basically, method overriding rules apply, even before the object is fully initialized.

Henry

Sorry, what do you mean by "method overriding rules apply" ? I could not understand. Thank you.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 16695
    
  19

Song Guo wrote:Sorry, what do you mean by "method overriding rules apply" ? I could not understand. Thank you.


How about "polymorphism rules apply"? When you override a method, the overridden method gets called.

Henry
Poornachandra Sarang
author
Greenhorn

Joined: Apr 17, 2012
Posts: 27
Constructor "initializes" the state of the object and is not used for "creating" the object as the name deceptively suggests. When JVM loads a class, its entire definition is injected into the memory. When a draw() method is called in the superclass constructor, the runtime looks up the polymorphic definition of the draw() method and finds that there is an overridden draw() method available and thus calls the subclass (RoundGlyph) draw() implementation. Try commenting the draw() method in the subclass and the runtime would call the superclass implementation. The point to note that the entire class definition is always available in memory and calling an object method has no connection to whether the object is fully initialized or not.
Jayesh A Lalwani
Bartender

Joined: Jan 17, 2008
Posts: 1272
    
    7

Note that this behavior is differrent that how C++ works, so it might surprise you if you are coming from C++. If you implement a similar program in C++, it will output "Glyph.draw()" instead of "RoundGlyph draw, radius = 0". This is beause in C++ the constructors are called as the object is being constructed, whereas in Java the constructor is called after the object is constructed.

Surprisingly, if you try the same thing in C#, you get the same result as Java
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 32694
    
    4
I am not at all surprised by anything giving the same result in C# as in Java™. Although Java™ is not at all similar to C++, C# is very similar to Java™.

On a different note, this sort of behaviour is why it is generally a good rule that all instance methods called from a constructor should have private access or be marked final.
Martin Vajsar
Bartender

Joined: Aug 22, 2010
Posts: 2331
    
    2

Jayesh A Lalwani wrote:This is beause in C++ the constructors are called as the object is being constructed, whereas in Java the constructor is called after the object is constructed.

Not exactly.

The object is incrementally constructed by the chain of constructors, starting at the Object constructor and going down the hierarchy chain. If a method overridden by the subclass is called from superclass constructor, the subclass'es fields will not be initialized yet (even the final fields). The overridden method will see the value of such final field as null; if the same method is invoked after the object is fully created, it will see the "correct" value of the final field. Therefore, though final, the field can be observed to "change".

Calling non-final methods from constructors should therefore be avoided to prevent issues like this (note that private methods are by definition final - they cannot be overridden). If you do invoke an overriddable method from a constructor, you should document that clearly so that the subclasses know not to access any fields of the subclass in their version of the method.
 
I agree. Here's the link: http://ej-technologies/jprofiler - if it wasn't for jprofiler, we would need to run our stuff on 16 servers instead of 3.
 
subject: a surprise behavior of polymorphic methods inside constructors in 《Thinking in Java》
 
Similar Threads
which draw() is called?
cannot resolve symbol
Constructors and Polymorphism
polymorphic method in abstract constructor