多态正常工作的关键在于子类重写方法时访问权限不可变窄:父类protected可升为public,包权限可升为protected或public,public只能保持;若收窄则编译报错,因破坏里氏替换原则。

多态能正常工作,关键在于子类重写方法时访问权限不能变窄——但可以提升。这不是“可选优化”,而是Java语言强制保障里氏替换原则和运行时多态的底层机制。
为什么允许提升访问权限?
核心是为了保证“父类引用指向子类对象”时调用依然合法且行为一致。如果父类方法是 protected,外部代码通过父类类型调用它没问题;子类若把它改成 public,调用依然成功,只是可见范围更广了——这不破坏原有契约,反而增强了可用性。
反过来说,如果子类擅自降级为 private 或包权限,父类引用调用就会编译失败,多态直接崩塌。
合法的权限提升组合
以下写法全部通过编译,且符合多态要求:
- 父类 protected → 子类 public
- 父类 包权限(默认) → 子类 protected 或 public
- 父类 public → 子类只能保留 public(不能再扩大)
哪些情况会报错?
只要出现“权限收窄”,编译器立刻拒绝:
- 父类 public → 子类写 protected、包权限或 private
- 父类 protected → 子类写包权限或 private
- 父类包权限 → 子类写 private
注意:private 方法无法被继承,子类中同名方法不是重写,而是全新定义,与多态无关。
实际影响:看引用类型,不看实现类
哪怕子类把方法提到了 public,如果你用的是父类引用(如 Animal a = new Dog();),能否调用该方法,只取决于父类声明的权限。子类提升权限不会让原本不可见的方法“意外可见”,它只是确保多态调用不因权限问题中断。











