1、首先我们先看几个类:Dog,Cat,Bird,这三个类是独立的,这里重写了每一个类的构造器,并输出对应的类名,如下图所示:
2、接下来再建立几个有继承关系的类:People,YelloPeople,Man,后面的类继承前面的类,如下图所示:
3、最后建立一个测试类,如下图所示,那么请大家不要看后面的输出结果,先思考下这个类输出的顺序是什么
4、new TestMan() 执行后,首先会去初始化TestMan这个类,而初始化首先就是调用构造器,而当继承的时候,意味着在子类中,可以访问父类中任何声明为public和protected的成员,那么为了确保这一目的,唯一的方法就是先调用父类构造器,所以前三个输出People,YellowPeople,Man,这时候所有的父类都初始化完了(隐式的继承不在讨论之类),接下来就才开始初始化TestMan这个类,接下来的顺序就很好理解了,定义的三个类都是独立的,所以都按顺序输出了其构造器,最后输出了TestMan自己的构造器,如下图所示:
5、还有一个问题值得考虑,假如在一个构造器的内部调用正在构造的对象的某个动态绑定的方法,那么会发生什么事呢,请看下面的例子,这次的输出结果会是什么呢,我想可能很多人对输出结果会很惊讶
6、依据最开始的例子,我们知道,首先new Man(5)会去初始化其父类,所以第一句话输出before p髫潋啜缅eople run这个应该是没有疑问的,而父类构造器的第二行代码调用了run方法,可是这个方法已经被子类覆盖了,所以这时候会去调用子类的run方法,那么输出walkLength222=是没有疑问的,但是为什么walkLength会等于0呢,这是因为这时候还在初始化父类,并没有开始初始化子类,故而子类的属性并没有被初始化,而子类在被编译的时候编译器会给int类型的成员变量赋默认值0,所以会输出0,接下来输出after people run,然后才开始初始化子类,这时候子类的walkLength会被赋值为1,故而输出了1