throw语句只能抛出Throwable或其子类实例;直接抛出String等非Throwable类型会编译失败,抛出null虽编译通过但运行时触发NullPointerException;检查异常必须捕获或声明throws,而RuntimeException无需声明;自定义异常须继承Exception或RuntimeException,不可直接继承Throwable;throw后代码不可达,但finally块总会执行。

throw 语句只能抛出 Throwable 或其子类的实例
Java 中 throw 不是“扔出任意对象”,它要求操作数必须是 Throwable 类型(如 Exception、RuntimeException、Error 及其子类)。直接 throw new String("oops") 会编译失败,报错:incompatible types: String cannot be converted to Throwable。
常见误用场景:
- 混淆
throw和throws:前者是语句(抛出一个异常实例),后者是方法声明的一部分(声明可能抛出的异常类型) - 试图抛出
null:如throw null;编译通过,但运行时触发NullPointerException,且堆栈不指向你写的那行,排查困难 - 在非检查异常上下文中硬塞检查异常:比如没在方法签名加
throws IOException,却throw new IOException(),编译器直接拒绝
检查异常必须显式处理或声明,而 RuntimeException 不强制
用 throw 抛出 IOException、SQLException 这类检查异常(checked exception)时,编译器会强制你二选一:
- 用
try-catch捕获并处理 - 在当前方法签名中用
throws声明,把责任上抛给调用方
但抛出 IllegalArgumentException、NullPointerException 等运行时异常(unchecked),则无此限制。例如:
立即学习“Java免费学习笔记(深入)”;
void parseAge(String s) {
if (s == null || s.trim().isEmpty()) {
throw new IllegalArgumentException("age string cannot be null or empty"); // ✅ 合法,无需 throws
}
}
这种灵活性常被用于参数校验,但要注意:过度依赖 unchecked 异常会让调用方失去编译期提醒,容易漏处理关键错误分支。
自定义异常要继承 Exception 或 RuntimeException
想用 throw 抛出自定义异常,必须让类继承 Throwable 的合法子类。推荐方式:
- 业务逻辑错误且希望调用方显式应对 → 继承
Exception(检查异常) - 编程错误或不可恢复状态(如配置缺失、非法状态)→ 继承
RuntimeException(运行时异常)
示例:
class InsufficientBalanceException extends Exception { // ✅ 检查异常
InsufficientBalanceException(String msg) { super(msg); }
}
class InvalidSessionException extends RuntimeException { // ✅ 运行时异常
InvalidSessionException(String msg) { super(msg); }
}
别直接继承 Throwable —— 这样既不是检查也不是运行时异常,JVM 行为未定义,多数 IDE 和工具链不识别。
throw 后的代码不会执行,但 finally 总会运行
throw 是立即终止当前方法执行的控制流语句。它后面的代码属于“不可达代码”(unreachable code),编译器会报错:
int getValue() {
throw new RuntimeException();
return 42; // ❌ 编译错误:unreachable statement
}
但若在 try 块中 throw,且存在 finally,则 finally 一定会执行,哪怕它自己也 throw 新异常(此时原异常会被覆盖):
try {
throw new IOException("read failed");
} finally {
System.out.println("cleanup done"); // ✅ 会打印
throw new RuntimeException("cleanup failed"); // ✅ 覆盖上面的 IOException
}
这点在资源清理逻辑中特别关键:别假设 throw 之后就“安全退出”了,finally 的副作用可能改变异常传播路径。








