behavior of polymorphic methods inside constructor

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值