throw用于方法体内主动抛出异常对象,需用new创建实例,执行后中断流程;抛出RuntimeException子类无需处理,抛出Exception等受检异常则必须try-catch或throws声明。

throw 是“真扔”,throws 是“预告要扔”——一个执行动作,一个契约声明。
throw 怎么用?在方法里主动抛出一个异常对象
它必须出现在方法体内部,后面跟的是 new 出来的异常实例,一执行就中断当前流程,后续代码不运行。
- 只能抛一个异常对象,比如
throw new IllegalArgumentException("用户名不能为空") - 抛
RuntimeException及其子类(如IllegalArgumentException、NullPointerException)时,编译器不强制你处理;但抛Exception或IOException这类受检异常(checked exception),就必须用try-catch包住,或在方法上加throws声明 - 常见误写:
throw IllegalArgumentException(错!缺new和括号),正确是throw new IllegalArgumentException("xxx") - 典型场景:参数校验失败、业务规则被破坏(如年龄为负数、订单状态非法)
public void setAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负数"); // ✅ 正确:抛对象
}
this.age = age;
}
throws 怎么用?在方法签名末尾声明可能抛出的异常类型
它不抛异常,只是告诉调用者:“我这个方法内部可能会冒出这些异常,你得自己兜着。”
- 写在方法返回类型之后、方法体之前,后面跟的是异常类名,不是对象,比如
throws IOException, SQLException - 可声明多个异常,用逗号分隔;只对受检异常有编译强制约束,运行时异常加不加都行(但加了更利于调用方预判)
- 子类重写父类方法时,
throws声明的异常类型不能比父类更宽(比如父类声明throws IOException,子类不能改成throws Exception) - 本质是责任上移:你不想在本层处理,就用
throws把异常“甩”给上层调用者
public void readFile(String path) throws FileNotFoundException, SecurityException {
File file = new File(path);
if (!file.exists()) {
throw new FileNotFoundException("文件不存在: " + path); // ✅ 内部 throw,外部 throws 呼应
}
// ...
}
为什么它们经常一起出现?配合使用才符合 Java 异常处理逻辑
单独用 throw 抛受检异常却不声明 throws,编译直接报错;只写 throws 却没在方法里真正 throw,虽然不报错,但属于“虚假预警”,会误导调用方。
立即学习“Java免费学习笔记(深入)”;
- 典型组合链:
方法内 throw new IOException()→方法声明加 throws IOException→调用方用 try-catch 处理,或继续 throws 上抛 - 不要在
catch块里吞掉异常后一声不吭,该包装再抛就用throw new BusinessException("xxx", e),并确保方法头有对应throws - 自定义异常建议继承
RuntimeException(免去处处throws的繁琐),除非你明确需要强制调用方处理(比如金融类系统对某些错误必须显式响应)
容易踩的坑:new、位置、类型、责任归属全乱套
最常翻车的点不在逻辑,而在语法和语义混淆:
-
throw后面漏new,写成throw IOException→ 编译失败 - 把
throws错写在方法体内(比如放在if里)→ 语法错误 - 抛
IOException却没throws,也没try-catch→ 编译报错 “Unhandled exception type IOException” - 在
finally块里又throw新异常,导致原始异常丢失(异常覆盖)→ 应该用带cause构造器:throw new RuntimeException("清理失败", e) - 过度使用
throws Exception(万能兜底)→ 掩盖真实异常类型,破坏接口契约,调用方无法针对性处理
记住最简判断法:throw 后有 new 就是对的,throws 后有 Exception 类名且在方法签名末尾,也是对的。错的永远是位置、对象/类型混淆、责任推脱不清。








