If you call a dynamically bound method inside a constructor, the overridden definition for that method is also used. However, the effect of this call can be rather unexpected because the overridden method is called before the object is fully constructed. This can conceal some difficult-to-find bugs.
If you do this inside a constructor, you can call a method that might manipulate members that haven’t been initialized yet—a sure recipe for disaster. Here’s the problem:
// polymorphism/PolyConstructors.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Constructors and polymorphism
// don't produce what you might expect
class Glyph {
void draw() {
System.out.println("Glyph.draw()");
}
Glyph() {
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() after draw()");
}
}
class RoundGlyph extends Glyph {
private int radius = 1;
RoundGlyph(int r) {
radius = r;
System.out.println("RoundGlyph.RoundGlyph(), radius = " + radius);
}
@Override
void draw() {
System.out.println("RoundGlyph.draw(), radius = " + radius);
}
}
public class PolyConstructors {
public static void main(String[] args) {
new RoundGlyph(5);
}
}
/* My Output:
Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5
BUILD SUCCESSFUL
Total time: 1.557 secs
*/
The Glyph constructor calls ovrriding method Glypyh.draw(), and the call ends up in RoundGlyph.draw() , which would seem to be the intent. The output shows that when Glyphs constructor calls draw() , the value of radius isn’t even the default initial value 1. It’s 0. This would probably result in either a dot or nothing at all drawn on the screen, and you’d be left staring, trying to figure out why the program won’t work.
The complete order of initialization is:
1. The storage allocated for the object is initialized to binary zero before anything else happens.
2. The base-class constructors are called as described previously. Now the overridden draw() method is called (yes, before the RoundGlyph constructor is called), which discovers a radius value of zero, due to Step 1.
3. Member initializers are called in the order of declaration.
4. The body of the derived-class constructor is called.
There’s an upside to this:
1. Everything is at least initialized to zero (or whatever zero means for that particular data type) and not just left as garbage.
for better understand, please read below content.
2. You should be horrified at the outcome of this program. You’ve done a perfectly logical thing, and yet the behavior is mysteriously wrong, with no complaints from the compiler. Bugs like this can easily be buried and take a long time to discover.
As a result, a good guideline for constructors is “Do as little as possible to set the object into a good state, and if you can possibly avoid it, don’t call any other methods in this class.”
for better understand, please read below content.
Java constructor initialize oder
references:
1. On Java 8 - Bruce Eckel
2. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/polymorphism/PolyConstructors.java