Java方法覆盖的核心约束是访问权限不能变窄、异常范围不能扩大,以保障多态下父类引用调用子类对象时的一致性与安全性。

Java方法覆盖(Override)不是简单地“重写同名方法”,而是面向对象多态机制的关键支撑。它的约束不是语法随意性,而是为了保障父类引用调用子类对象时行为的一致性与安全性。核心就两点:访问权限不能变窄,异常范围不能扩大。
访问权限必须“持平或放宽”
子类覆盖方法的访问修饰符,不能比父类方法更严格。否则,当用父类引用指向子类对象时,编译器会认为该方法“可见”,但运行时实际调用的子类方法却不可见——这就破坏了多态的基本契约。
- 父类是 protected,子类可改为 public,但不能是 default(包私有)或 private
- 父类是 public,子类只能是 public;改用 protected 或更低会直接编译失败
-
private 方法无法被继承,因此谈不上覆盖;子类中同名方法只是新定义,加
@Override注解会报错
抛出异常必须“不新增、只缩小”
覆盖方法声明的异常类型,必须是父类方法所声明异常的子类,或完全不抛出异常。这不是限制能力,而是确保异常处理逻辑在父类视角下依然完整有效。
- 父类方法声明
throws IOException,子类可声明throws FileNotFoundException(它是IOException的子类),也可不写throws - 若子类擅自加了
throws SQLException,而父类没声明该异常,那么用父类引用调用时,原有catch(IOException e)就捕获不到这个新异常,编译器会拒绝 - 注意:“异常更多”不是指数量多,而是类型范围更宽——只要新增了父类未声明的异常类型,哪怕只一个,也不允许
其他关键前提与常见误区
访问和异常只是两大显性约束,但覆盖成立的前提和边界同样重要:
立即学习“Java免费学习笔记(深入)”;
- 方法签名必须完全一致:方法名、参数个数与类型、顺序三者缺一不可;返回值基本类型必须相同,引用类型允许协变(即子类返回更具体的子类型)
- 静态方法不能被覆盖,只能被隐藏;私有方法、构造方法不参与覆盖机制
-
@Override注解不是可选装饰,而是强制校验手段——它能帮你提前发现签名错误、权限误设或异常越界等低级但致命的问题
这些规则背后没有魔法,全是为动态绑定服务:让程序在编译期就能确定调用安全,在运行期不因权限或异常失控而崩溃。写覆盖方法时,先问自己一句——如果这里用的是父类类型变量,这段代码还能顺利编译和运行吗?答案就是约束的起点。


















