Java继承中同名属性访问问题:父类引用为何仅能访问父类属性
问题描述
我定义了两个类A和B,其中B继承自A。两个类均包含一个int类型的属性w:A中的w为public实例属性,B中的w为public静态属性。我创建了父类引用指向子类对象的实例:A a = new B(),但尝试访问属性时,仅能访问A类的变量和方法,即便实例实际是B类的。我原以为只有当两类没有同名方法或变量时才会出现这种情况,但此处两者存在同名属性w,却只能访问A类中存储的w值,请问这是为什么?
代码示例
类A
public class A { public int w; private static String str = "K"; public A() { str+="B"; w+=str.length(); str+=w; } @Override public String toString() { return str.charAt(w-2)+"P"; } }
类B
public class B extends A { public static int w = 2; private String str = "W"; public B(int x) { w+=super.w; str+=super.toString()+w; } @Override public String toString() { return super.toString() + str; } }
测试类Q1
public class Q1 { public static void main(String[] args) { A a = new A(); A a2 = new B(1); System.out.println(a); System.out.println(a.w); System.out.println(a2); System.out.println(a2.w); B b = new B(2); System.out.println(b); } }
问题解答
核心原因:Java的成员属性不支持多态(动态绑定),它是编译期静态绑定的;只有方法才会在运行期根据实际对象类型动态绑定。
具体解释:
编译期锁定属性访问目标
当你用父类类型的引用A a2 = new B()访问a2.w时,编译器只认引用的「编译时类型」——也就是A,所以直接绑定到A类中定义的w属性,完全不会考虑运行时实际对象是B类型。子类同名属性是「隐藏」而非「重写」
子类B中的w和父类A的w是两个完全独立的变量,只是名字相同而已。这种情况叫做属性隐藏,和方法的「重写(Override)」本质不同:
- 方法重写会让父类引用在运行时调用子类的实现;
- 属性隐藏只是子类新增了一个同名变量,父类的
w依然存在于子类对象中,父类引用只能看到自己类型定义的那个w。
- 对比方法的动态绑定特性
比如你的代码中toString()方法被B重写了,所以调用a2.toString()时,运行期会根据实际对象是B来执行B的toString()实现——这就是方法的多态,但属性没有这个机制。
结合你的代码验证
看测试类的输出:
a2.w输出的是父类A的实例属性w的值(由A的构造函数计算得出);- 用
B类型的引用b访问b.w时,才会拿到子类B中定义的静态w变量。
这两个w是完全独立的变量,存储在不同的内存位置,父类引用只能访问自己类型中声明的那个属性。
内容的提问来源于stack exchange,提问作者dudex198
相关产品推荐
相关产品推荐

