Java父类引用指向子类对象时访问实例变量为何输出10而非20
问题解答
核心结论
你的理解存在偏差,这是Java的成员变量不支持多态重写的典型表现:Java的多态特性仅对成员方法生效,成员变量只会根据引用的声明类型静态绑定取值,不会根据实际创建的实例类型动态匹配。
执行逻辑梳理
你提供的测试代码如下:
class A { int i = 10; } class B extends A { int i = 20; } public class MainClass { public static void main(String[] args) { A a = new B(); System.out.println(a.i); //Output of this line } }
逐段拆解运行逻辑:
- 类加载阶段:JVM会分别加载A、B、MainClass三个类。B类中定义的
i并不是重写父类A的i,只是和父类属性同名的、属于B类本身的独立属性,最终创建的B类实例中,会同时存在两个i属性:一个继承自父类A值为10,一个属于子类B值为20。 - 执行
A a = new B();时:会在堆内存中创建B类的实例,同时在栈中创建声明类型为A的引用a指向这个B实例。 - 执行
System.out.println(a.i);时:JVM判断引用a的声明类型是A,直接绑定A类定义的i属性取值,因此输出结果为10。
扩展说明
如果要获取B类定义的i属性值,只需要将引用强转为B类型即可,修改代码如下:
System.out.println(((B)a).i);
上述代码运行后会输出20,因为此时引用的声明类型被转为B,会绑定B类定义的i属性取值。
内容的提问来源于stack exchange,提问作者user15294548
相关产品推荐
相关产品推荐

