重写方法时返回值类型须为父类返回类型的协变类型(相同或子类),检查型异常只能缩小或不抛出,运行时异常无限制;编译器严格校验并报错违规情况。

重写方法时,返回值类型必须是父类方法返回类型的协变类型(即相同或其子类型),异常只能抛出父类方法声明中已有的检查型异常的子类,或不抛出检查型异常;运行时异常不受限制。
返回值类型必须满足协变规则
Java 允许重写方法使用更具体的返回类型(协变返回类型),但不能更宽泛。前提是返回类型是引用类型,且子类返回类型是父类返回类型的子类或相同类型。
- ✅ 合法:父类返回
Object,子类重写返回String或List> - ✅ 合法:父类返回
Number,子类返回Integer - ❌ 非法:父类返回
String,子类返回Object(变宽,破坏多态安全) - ❌ 非法:父类返回基本类型(如
int),子类不能改为long或包装类(基本类型不支持协变)
检查型异常(checked exception)只能缩小或不抛出
子类重写方法声明的 throws 子句,不能新增父类方法未声明的检查型异常,也不能声明更宽泛的检查型异常类型。
- ✅ 合法:父类声明
throws IOException,子类可声明throws FileNotFoundException(FileNotFoundException是IOException的子类) - ✅ 合法:父类声明
throws SQLException,子类可不写throws(即不抛出任何检查型异常) - ❌ 非法:父类没声明异常,子类却写
throws IOException - ❌ 非法:父类声明
throws IllegalArgumentException(运行时异常),子类加throws IOException(检查型异常不允许新增)
运行时异常(unchecked exception)完全自由
RuntimeException 及其子类(如 NullPointerException、IllegalArgumentException)不受重写规则约束。子类方法可以抛出任意运行时异常,无论父类是否声明。
- ✅ 父类没写
throws,子类可自由加throws IllegalArgumentException - ✅ 父类声明
throws RuntimeException,子类可改 throwConcurrentModificationException - ⚠️ 注意:虽然语法允许,但应保持语义合理——不该让调用方因重写而意外遇到新运行时异常
编译器如何验证这些规则
Java 编译器在编译子类时会严格比对父类方法签名(含返回类型和 throws 列表)。只要违反上述任一限制,就会报编译错误,例如:
- "Cannot override X with return type Y" —— 返回类型不协变
- "Overridden method does not throw Y" —— 新增了未声明的检查型异常
- "Exception Y is not compatible with throws clause in X" —— throws 类型不兼容
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











