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

为何将子类对象赋值给父类引用时编译器不报错?附代码疑问

Java父类引用指向子类对象的核心问题解答

基础代码示例

class Base {
    public void show() {
        System.out.println("Base class show() method called");
    }
}

class Derived extends Base {
    public void show() {
        System.out.println("Derived class show () method called");
    }
}

public class Main {
    public static void main(String[] args) {
        Base b = new Derived();// 为何Java允许创建子类对象并赋值给父类引用
        b.show();              // 父类如何持有并使用子类的引用
    }                              
}

问题1:父类引用为何能指向子类对象?父类是如何持有并使用子类引用的?

这是Java多态的核心特性:子类本质是父类的特殊类型(Derived is a Base),所以父类引用可以安全指向子类对象。

内存层面,new Derived()创建的是完整子类对象,包含父类所有属性和方法。父类引用b只是限制了可访问的成员范围——它只能识别父类定义的方法/属性,但运行时会根据对象实际类型(而非引用类型)调用子类重写的实现(比如show()方法),这就是动态绑定。


问题2:子类新增方法后,父类引用能否访问该方法?

先看对应代码示例:

class Derived extends Base {
    public void show() {
        System.out.println("Derived class show () method called");
    }
    public void poo() {
        System.out.println("take a poo");
    }
}

public class Main {
    public static void main(String[] args) {
        Base b = new Derived();
        b.show();   
        b.poo(); // 该行代码会编译报错
    }                              
}

答案是不能。父类引用b的编译类型是Base,编译器只会检查Base类中是否存在poo()方法——显然不存在,因此直接编译失败。

如果要调用子类新增方法,需先将父类引用强制类型转换为子类类型:

((Derived) b).poo(); // 可正常调用

转换前建议用instanceof检查类型,避免ClassCastException:

if (b instanceof Derived) {
    ((Derived) b).poo();
}

问题3:为何Java允许将子类引用赋值给父类,且无警告或错误?

这完全符合面向对象设计原则:

  1. 里氏替换原则:子类必须能替换父类的所有使用场景,这是继承的核心要求。既然子类是父类的扩展,用父类引用指向子类对象是安全的,不会破坏程序正确性。
  2. 多态的基础:这种赋值是实现多态的前提——允许用统一的父类接口处理不同子类对象,比如用List引用指向ArrayList或LinkedList,无需关心具体实现,提升代码扩展性与复用性。
  3. 类型安全:编译器会校验子类与父类的继承关系,确保赋值操作类型安全,因此无需警告或错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 17:07:56