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

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的成员属性不支持多态(动态绑定),它是编译期静态绑定的;只有方法才会在运行期根据实际对象类型动态绑定。

具体解释:

  1. 编译期锁定属性访问目标
    当你用父类类型的引用A a2 = new B()访问a2.w时,编译器只认引用的「编译时类型」——也就是A,所以直接绑定到A类中定义的w属性,完全不会考虑运行时实际对象是B类型。

  2. 子类同名属性是「隐藏」而非「重写」
    子类B中的w和父类A的w是两个完全独立的变量,只是名字相同而已。这种情况叫做属性隐藏,和方法的「重写(Override)」本质不同:

  • 方法重写会让父类引用在运行时调用子类的实现;
  • 属性隐藏只是子类新增了一个同名变量,父类的w依然存在于子类对象中,父类引用只能看到自己类型定义的那个w。
  1. 对比方法的动态绑定特性
    比如你的代码中toString()方法被B重写了,所以调用a2.toString()时,运行期会根据实际对象是B来执行B的toString()实现——这就是方法的多态,但属性没有这个机制。

结合你的代码验证

看测试类的输出:

  • a2.w输出的是父类A的实例属性w的值(由A的构造函数计算得出);
  • 用B类型的引用b访问b.w时,才会拿到子类B中定义的静态w变量。

这两个w是完全独立的变量,存储在不同的内存位置,父类引用只能访问自己类型中声明的那个属性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 15:00:45