throw是方法内抛出异常的语句,throws是方法声明中预告可能抛出异常的关键字;前者创建并抛出Throwable实例,后者声明受检异常类型以完成异常传递链。

理解 throw 和 throws 的协作机制,关键在于抓住“谁抛、谁声明、谁处理”这条主线。它们不是独立存在,而是异常从产生到传递过程中的两个必要环节。
throw 是异常的“发起者”
它出现在方法内部,作用是实实在在地创建并抛出一个异常对象。一旦执行到 throw 语句,当前方法立刻停止,控制权交还给调用栈上层。
- 必须抛出 Throwable 或其子类的实例,比如
throw new IllegalArgumentException("参数非法") - 抛出后,方法后续代码不再执行(哪怕只差一行)
- 它不关心异常最终怎么处理,只负责“扔出去”
throws 是异常的“预告单”
它写在方法签名末尾,作用是提前告知调用者:“我这个方法可能会把某种异常甩给你,请你做好准备。”
- 只声明类型,不创建对象;可以列多个,用逗号分隔,如
throws IOException, SQLException - 对受检异常(checked exception)是强制要求:要么 throws 声明,要么 try-catch 捕获
- 对非受检异常(如 RuntimeException 及其子类),throws 不是必需的,但写上更清晰
协作的本质是异常传递链
throw 抛出的异常,需要通过 throws 向上声明,才能合法地交给外层方法处理。这就像快递发货:throw 是打包发货,throws 是贴运单——没运单,快递公司(编译器)就不让发。
立即学习“Java免费学习笔记(深入)”;
- 例如:
void check(int x) throws IllegalArgumentException { if (x —— 这里 throw 提供了“货”,throws 提供了“单” - 如果 throw 的是 IOException(受检异常),而方法没写 throws,编译直接报错
- 如果 throw 的是 NullPointerException(非受检),即使不写 throws,也能编译通过,但逻辑上仍会向上抛
调用方必须接住或再转手
当一个方法用 throws 声明了异常,调用它的代码就进入了“责任区”:必须用 try-catch 捕获,或者自己也加 throws 继续往外推。
- 这是 Java 编译器强制的契约,尤其针对文件、网络等外部资源操作
- 不处理也不声明,编译失败;这不是风格问题,是语言规则
- 这种设计让异常路径清晰可见,避免“静默失败”


















