贝利信息

Java多态对于初学者最难理解的点在哪里

日期:2026-01-21 00:00 / 作者:星降
字段访问走静态绑定(编译时看声明类型),方法调用走动态绑定(运行时看实际类型);Java不支持字段多态,子类同名字段仅隐藏父类字段,而非重写。

为什么调用的是子类方法,但字段访问的却是父类的?

这是初学者最常卡住的地方:明明 Animal a = new Dog();a.speak() 调的是 Dog.speak(),可 a.name 却是父类定义的值,甚至子类重写了同名字段也无效。

根本原因在于——方法调用走动态绑定(运行时看实际类型),字段访问走静态绑定(编译时看声明类型)。Java 不支持字段多态。

父类引用能调用子类新增的方法吗?

不能。比如 Animal a = new Dog();,即使 Dogfetch() 方法,a.fetch() 编译直接报错:cannot resolve symbol fetch

因为编译器只认 a 的声明类型(Animal),它不知道背后是不是 Dog。这和多态无关,是类型系统的基本规则。

构造器里调用被重写的方法为什么危险?

在父类构造器中调用一个可被子类重写的方法(如 this.init()),而子类恰好重写了它,结果会出人意料:方法确实执行了子类版本,但此时子类字段还未初始化(仍是默认值)。

class Parent {
    String value = "parent";
    Parent() {
        init(); // 这里会调到 Child.init()
    }
    void init() { System.out.println("Parent init"); }
}

class Child extends Parent {
    String value = "child";
    Child() { super(); }
    @Override
    void init() { System.out.println(value); } // 打印 null!
}

这是因为子类构造器还没开始执行,value 字段尚未赋值。

多态本身不难,难在它

和其他语言机制(字段绑定、构造顺序、类型检查)交织在一起。最容易被忽略的,就是字段访问和方法调用根本不是一回事——这点没理清,后面所有困惑都由此而生。