Java中父类引用指向子类对象时成员变量与方法行为差异解惑
核心原因:方法动态绑定 vs 变量静态绑定
首先纠正一个理解偏差:A obj = new B();这句话的正确含义是创建一个B类的对象,但用A类型的引用变量指向它,并非“创建A类型对象并使用B的实现”,这是理解问题的关键。
接下来分两部分解释你遇到的差异:
1. 方法调用:动态绑定(多态特性)
Java中,非静态方法的调用是动态绑定的——编译阶段仅检查引用类型(此处为A)是否存在对应方法,而实际执行哪个类的方法,是在运行时根据对象的真实类型(此处为B)决定的。
在你的代码里,obj.display()的执行逻辑是:
- 编译时确认A类有
display()方法,通过编译校验; - 运行时JVM识别到实际对象是B,因此调用B类重写后的
display()方法,自然会使用B类的z,输出B's z is 20。
2. 成员变量调用:静态绑定
和方法不同,成员变量的访问是静态绑定的——编译阶段就直接根据引用类型(此处为A)确定要访问的变量,完全不考虑运行时的真实对象类型。
B类里的int z = 20;并不是“重写”A类的z,而是隐藏了父类的z。这意味着B对象的内存中同时存在两个独立的z:一个是继承自A的z(值10),一个是B自身定义的z(值20)。当你用A类型的引用obj访问obj.z时,编译器直接绑定到A类的z,因此输出10。
如果想要访问B类的z,你可以把引用强转为B类型:
System.out.println(((B)obj).z); // 输出20
另外你也能看到,B类的display()方法里的z会直接访问自身的z,因为在类内部,默认优先访问当前类定义的成员变量(如果存在隐藏父类变量的情况)。
内容的提问来源于stack exchange,提问作者Cheesewaffle
相关产品推荐
相关产品推荐

