父类构造器调用print方法为何执行子类重写方法?
Java代码输出解释与疑问解答
代码示例
父类A
public class A { public A() { this.print(); } public void print() { System.out.println("A"); } }
子类B
public class B extends A { int i; public B() { i=4; } @Override public void print() { System.out.println("calling B.print"); System.out.println(i); } }
测试类Tester
public class Tester { public static void main(String[] args) { A obj = new B(); obj.print(); } }
程序输出
calling B.print 0 calling B.print 4
疑问解答与原理说明
1. 为什么父类构造器的this.print()调用了子类的方法?
Java中非私有实例方法的调用是基于运行时对象的实际类型,而非编译时的声明类型。当你执行new B()创建对象时,this在父类构造器里指向的是正在初始化的子类B对象,而非父类A的对象。由于子类B重写了print()方法,所以运行时会调用子类的版本,而不是父类的print()。
2. 为什么第一次输出的i是0?
子类对象的初始化遵循固定顺序:
- 先执行父类构造器,此时子类的成员变量还处于默认初始化状态(int类型的默认值是0)
- 父类构造器调用子类的
print()时,子类构造器里的i=4还没执行,所以输出0 - 父类构造执行完成后,才会执行子类B的构造器,将
i赋值为4 - 最后调用
obj.print()时,i已经完成赋值,所以输出4
总结
父类构造器中的this.print()调用子类方法,是Java多态机制的核心特性——运行时根据对象实际类型匹配方法;而第一次输出0,是因为子类成员变量的显式初始化在父类构造执行之后才完成。
内容的提问来源于stack exchange,提问作者Roushan Kumar
相关产品推荐
相关产品推荐

