子类重写父类方法时,访问权限不能收窄、异常声明不能扩大,这是Java为保障多态安全和里氏替换原则设定的编译期强制规则;访问权限只能持平或放宽,checked异常只能缩小或保持,协变返回类型仅限引用类型向下兼容。

子类重写父类方法时,访问权限不能收窄、异常声明不能扩大——这两条是编译器强制拦截的硬性红线,不是建议,而是Java语言为保障多态安全设下的底层契约。
访问权限只能持平或放宽,绝不可收紧
父类方法的可见性决定了“谁能在哪调用它”,子类重写后必须维持甚至增强这一能力,否则父类引用指向子类对象时会直接失效。
- 父类是 public → 子类必须是 public(改
protected或private编译报错:Cannot reduce the visibility) - 父类是 protected → 子类可用
protected或public,但不能用默认(包私有)或private - 父类是默认(无修饰符)→ 子类可用默认、
protected或public,但不能是private - 父类是 private → 不可重写(子类同名方法只是独立声明,与继承无关)
检查型异常只能缩小或保持,不能扩大
这条规则只约束 checked exception(如 IOException、SQLException),运行时异常(RuntimeException 及其子类)完全不受限。
- 父类没声明 checked 异常 → 子类不能抛
IOException等,但可以抛IllegalArgumentException - 父类声明
IOException→ 子类可抛FileNotFoundException(它是IOException的子类),也可不抛,但不可抛Exception(更宽泛)或SQLException(无关类型) - 子类方法可以比父类抛得更少、更具体,但绝不允许更多、更笼统
协变返回类型:引用类型可向下兼容
这不是访问或异常规则,但常被误认为“红线松动”——它其实是安全放宽,仅适用于引用类型返回值。
- 父类返回
Animal→ 子类可返回Dog或Cat(子类实例天然可赋值给父类引用) - 父类返回
String→ 子类不能返回Object(扩大范围,编译失败) - 父类返回基本类型(如
int、boolean)或void→ 子类必须严格一致
这些限制的根本目的:守住里氏替换原则
所有规则都服务于一个目标:让 Animal a = new Dog(); a.makeSound(); 这样的调用永远成立且行为可预期。如果子类偷偷把 public 改成 protected,或把 FileNotFoundException 换成 Exception,外部代码按父类契约写的逻辑就会在编译期崩掉——Java选择提前拦截,而不是留到运行时出错。

















