Java多态安全依赖编译期强制验证:返回值须协变(子类型)、检查异常须收缩(更具体或不抛出)、访问权限不能更严格、final方法不可重写、static方法不参与重写,@Override注解提供校验防线。

Java 中多态依赖方法重写实现运行时动态绑定,而返回值和异常的合规性是保障多态安全的关键。它不是靠运行时检查,而是由编译器在编译阶段强制验证——只要不满足规则,代码就无法通过编译。
返回值必须满足协变原则
重写方法的返回类型不必完全相同,但必须是父类方法返回类型的子类型(即“协变返回类型”)。这是从 Java 5 开始支持的特性,目的是让子类能更精确地表达自己的行为,同时不破坏父类契约。
- 如果父类方法返回 Animal,子类可返回 Dog(Dog extends Animal)
- 如果父类方法返回 Object,子类可返回 String、List<?> 等任意具体类型
- 但不能反向:父类返回 String,子类不能返回 Object(那是更宽泛的类型,会破坏调用方预期)
检查异常必须遵循“异常上界收缩”规则
重写方法声明的检查异常(checked exception)只能比父类方法更少、更具体,或不抛出任何检查异常。这确保了用父类引用调用时,调用方按父类声明写的异常处理逻辑依然完备。
- 父类方法声明 throws IOException → 子类可声明 throws FileNotFoundException(IOException 的子类),或 throws(不抛出)
- 父类方法声明 throws SQLException → 子类不可声明 throws Exception(Exception 是 SQLException 的父类,范围更宽)
- 非检查异常(RuntimeException 及其子类)不受此限,可自由增删
访问权限与 final/static 限制共同支撑多态稳定性
这些看似“外围”的限制,实则为多态提供底层保障:
立即学习“Java免费学习笔记(深入)”;
- 子类重写方法的访问权限不能比父类更严格(如父类 public,子类不能 protected),否则父类引用在某些上下文中可能无法访问该方法,破坏多态调用一致性
- final 方法禁止重写,防止关键行为被意外覆盖,保证父类定义的契约不可绕过
- static 方法不参与重写(只可隐藏),因为静态绑定发生在编译期,与运行时多态机制无关
@Override 注解是多态安全的实践防线
显式添加 @Override 不仅提升可读性,更重要的是让编译器主动校验:当前方法是否真正在重写父类(或接口)中已有的方法。一旦签名、返回值或异常声明不合规,编译器立刻报错,把问题拦截在开发早期。
不加该注解虽不报错,但失去这一层防护——比如误将参数类型写错,可能变成重载而非重写,导致多态失效却无提示。


















