You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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对象初始化顺序与方法重写机制共同作用的结果:

  1. Java实例化子类对象的执行顺序为:
    • 初始化父类静态变量/静态代码块
    • 初始化子类静态变量/静态代码块
    • 初始化父类实例变量/实例代码块
    • 执行父类构造方法
    • 初始化子类实例变量/实例代码块
    • 执行子类构造方法
  2. 父类构造方法中调用了printValues(),而该方法被子类重写。此时父类构造执行时,子类的实例变量(a、b)还未完成初始化,只能取到默认值0。
  3. c是final实例变量,属于编译期常量或在实例初始化阶段立即赋值,因此能提前获取到300;d、e是静态变量,类加载阶段就已完成初始化,子类的静态变量值400、500已生效。

解决方案

  1. 禁止在父类构造中调用可重写的实例方法:将父类的printValues()改为私有方法或用final修饰,避免被子类重写,确保父类构造调用自身的方法。
    修正后的父类代码:
    class Super {
        // ... 其他属性不变
        
        private void printValues() { // 改为private
            System.out.print("Super : ");
            System.out.println(+a + " " + b + " " + c + " " + d + " " + e);
        }
    
        Super() {
            printValues();
        }
    }
    
  2. 调整初始化逻辑:不在父类构造中调用该方法,而是在子类构造完成后手动调用,确保子类实例变量已初始化。

内容的提问来源于stack exchange,提问作者KDPK Kasthurisinghe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 15:43:18