编译错误明确指出子类重写方法throws的检查异常不能比父类更宽泛:父类声明throws sqlexception,子类不可throws exception或ioexception;若父类未声明throws,子类不得添加任何检查异常;runtimeexception及其子类不受限制。

直接看编译错误信息,它会明确指出哪一行、哪个异常类型越界了。核心是子类重写方法的 throws 子句不能比父类声明的检查异常更宽泛——这是编译期强制规则,不是运行时问题。
看报错提示,定位越界异常类型
编译器报错类似:error: overridden method does not throw java.lang.Exception 或 Exception is not compatible with throws clause。
关键不是“抛了异常”,而是“抛了父类没承诺过的检查异常”。
比如父类方法声明 throws SQLException,子类却写了 throws Exception 或 throws IOException,这两个都比 SQLException 更宽,编译直接失败。
核对父类 throws 声明的完整继承链
不能只看父类方法写了什么异常,还要确认它是不是某个更宽泛异常的子类。例如:
- 父类声明
throws IOException→ 子类可写throws FileNotFoundException(合法,是子类) - 父类声明
throws IOException→ 子类写throws SQLException(非法,无关类型,不构成继承关系) - 父类没写
throws→ 子类加任何检查异常(如throws IOException)都会编译失败
检查方法体内是否隐式引入了新检查异常
常见诱因:子类方法里调用了可能抛出检查异常的代码,但没处理,又没在 throws 中声明对应父类允许的异常类型。例如:
- 父类方法签名是
void save() throws DataAccessException - 子类里写了
new FileOutputStream("log.txt")→ 这会触发IOException - 但
IOException不是DataAccessException的子类,也不在其继承链上 → 编译报错
此时必须二选一:用 try-catch 拦住 IOException 并转为运行时异常或内部处理;或确保所有新出现的检查异常都落在父类 throws 类型的继承范围内。
排除运行时异常干扰
RuntimeException 及其子类(如 IllegalArgumentException、NullPointerException)完全不受此限制。子类可以自由添加、删除、替换这些异常的 throws 声明,编译器不管。所以如果报错里提到的是这类异常,说明真正的问题不在这里——要回头再找检查异常的越界点。










