Java子类同名属性初始化后输出为0的原因咨询
Java子类实例化时属性初始化异常问题解析
定义Super父类与Sub子类,子类继承父类后,定义了与父类同名、同类型、同访问修饰符的属性并完成初始化。实例化子类时,输出结果中a、b属性值为0(预期为100、300),其余属性输出符合预期。
问题代码
class Super { int a = 10; private int b = 30; final int c = 30; static int d = 40; final static int e = 50; void printValues() { System.out.print("Super : "); System.out.println(+a + " " + b + " " + c + " " + d + " " + e); } Super() { printValues(); } } class Sub extends Super { int a = 100; private int b = 300; final int c = 300; static int d = 400; final static int e = 500; void printValues() { System.out.print("Sub : "); System.out.println(+a + " " + b + " " + c + " " + d + " " + e); } } class TwentyFIve { public static void main(String args[]) { new Sub(); } }
输出对比
- 预期输出:
Sub : 100 300 300 400 500 - 实际输出:
Sub : 0 0 300 400 500
原因分析
这是Java对象初始化顺序与方法重写机制共同作用的结果:
- Java实例化子类对象的执行顺序为:
- 初始化父类静态变量/静态代码块
- 初始化子类静态变量/静态代码块
- 初始化父类实例变量/实例代码块
- 执行父类构造方法
- 初始化子类实例变量/实例代码块
- 执行子类构造方法
- 父类构造方法中调用了
printValues(),而该方法被子类重写。此时父类构造执行时,子类的实例变量(a、b)还未完成初始化,只能取到默认值0。 c是final实例变量,属于编译期常量或在实例初始化阶段立即赋值,因此能提前获取到300;d、e是静态变量,类加载阶段就已完成初始化,子类的静态变量值400、500已生效。
解决方案
- 禁止在父类构造中调用可重写的实例方法:将父类的
printValues()改为私有方法或用final修饰,避免被子类重写,确保父类构造调用自身的方法。
修正后的父类代码:class Super { // ... 其他属性不变 private void printValues() { // 改为private System.out.print("Super : "); System.out.println(+a + " " + b + " " + c + " " + d + " " + e); } Super() { printValues(); } } - 调整初始化逻辑:不在父类构造中调用该方法,而是在子类构造完成后手动调用,确保子类实例变量已初始化。
内容的提问来源于stack exchange,提问作者KDPK Kasthurisinghe
相关产品推荐
相关产品推荐

