[Java学习日记09】聊聊throw和throws
前言:关于“谁来背锅”的哲学讨论
坐标:图书馆 2 楼靠窗位(今天终于抢到了有插座的位置!)
状态:冰美式特浓,脑细胞正在高速运转。
碎碎念: 兄弟们,今天写代码的时候,我陷入了深深的思考。 有时候程序出错了,我是该直接在那儿处理掉呢,还是假装没看见,把球踢给调用我的那个人?
这在 Java 里其实就是
throw和throws的博弈。学长告诉我:“写程序就像在寝室打扫卫生,有的垃圾你自己随手捡了(try-catch),有的垃圾你得贴个告示告诉室友‘这儿有垃圾,谁最后走谁倒’(throws)。”今天咱就来扒一扒这对“甩锅”兄弟的底细,看看在 Java 的异常战场上,它们到底是怎么配合演戏的!
🚀 目录
-
-
2.1 什么时候主动扔异常?
-
2.2 它的语法潜规则
-
-
-
3.1 为什么要有 throws?
-
3.2 运行时异常 vs 编译时异常的不同态度
-
1. 一眼定乾坤:实干家 vs 预言家
在 Java 世界里,你可以通过名字后面的那个 s 来快速区分它们:
-
throw (实干家):它是一个动作,表示“我现在就要抛出一个异常”。
-
throws (预言家):它是一个声明,表示“我这儿可能会出现异常,大家小心”。
大学生比喻:
-
throw就像你亲手把一个挂科的消息发给老妈。 -
throws就像你在成绩单信封上贴个条子:“内有挂科通知,打开前请自备速效救心丸”。
2. throw:亲手扔出的“手榴弹”
throw 关键字后面跟着的是一个具体的异常对象。
2.1 什么时候主动扔异常?
通常是在逻辑判断不通过的时候。比如你写一个“发工资”的方法,如果金额是负数,这就不符合常理,你得抛个异常:
public void paySalary(double money) {
if (money < 0) {
// 主动制造并抛出一个异常,逻辑到此中断
throw new IllegalArgumentException("工资居然是负数?老板你良心呢!");
}
System.out.println("成功发放工资:" + money);
}
2.2 它的语法潜规则
-
throw必须写在方法体内部。 -
每次只能抛出一个具体的异常实例。
-
只要
throw一执行,方法剩下的代码就再也不会跑了(除非它在 try 块里且有 finally)。
3. throws:优雅的“免责声明”
throws 写在方法头(参数列表后面),后面跟着的是异常类名。
3.1 为什么要有 throws?
Java 编译器非常严谨。如果你在方法里干了一些“危险动作”(比如读文件),编译器会强迫你处理异常。如果你不想在方法里写繁琐的 try-catch,你就得用 throws 告诉上级:“我这儿可能有炸弹,接球的人你自己看着办。”
3.2 两种异常的不同待遇
-
运行时异常 (RuntimeException):你想声明就声明,不声明编译器也不管你。
-
编译时异常 (Checked Exception):必须声明!如果不声明又不捕获,代码根本编译不过去。
// 这是一个危险的方法,它声明了可能会抛出 FileNotFoundException
public void readFile(String path) throws FileNotFoundException {
// 这里并没有 try-catch,因为我用 throws 把锅甩出去了
FileInputStream fis = new FileInputStream(path);
}
4. 核心对撞:一张表教你做人
|
特征 |
throw |
throws |
|---|---|---|
|
位置 |
方法体内 |
方法名后面,参数列表后 |
|
后面跟的是... |
异常对象 ( |
异常类型 ( |
|
数量 |
只能抛出一个对象 |
可以声明多个类型(逗号隔开) |
|
作用 |
主动制造异常,结束当前方法 |
提醒调用者处理异常,是一种免责声明 |
|
性质 |
实际的动作(抛球) |
可能的危险预告(看球) |
5. 深度思考:甩锅的终点在哪里?
很多同学问我:“如果我也 throws,我上级也 throws,那最后这个锅谁背?”
答案是:JVM(虚拟机)。 如果异常一直向上甩,最后没人处理,JVM 就会无奈地站出来,把异常信息打印在控制台(也就是咱们最怕的红字),然后直接强制关掉你的程序。
所以,甩锅虽爽,但终究得有人接。 优秀的程序员会在最合适的地方(通常是 Controller 层或 UI 交互层)通过 try-catch 把锅接住,给用户一个体面的提示。
6. 面试高频考点演练
Q1:throw 后面的代码还会执行吗? 答案:除了在 finally 块里,否则 throw 后面的代码都是 Unreachable(不可达),编译器会报错。
Q2:如果重写(Override)的方法,父类没写 throws,子类能写吗? 答案:不能!子类抛出的编译时异常不能大于父类。
-
比喻:老爸说这事儿没危险,你不能跳出来说这事儿要人命。
Q3:throw null 会发生什么? 答案:会触发 NullPointerException。因为 throw 后面必须是一个有效的异常对象。
7. 结语
写完这篇日记,我终于把项目里那些乱七八糟的 try-catch 清理掉了一部分。有些该甩给全局异常处理器处理的锅,果断用 throws 甩了出去。
作为大学生的我们:
-
要敢于
throw(当数据不对,要有拒绝的勇气)。 -
要学会
throws(声明风险,保护自己)。 -
但最后一定要有
try-catch(负责到底,才是真爷们)。
如果你也被这俩“兄弟”绕晕过,点个赞支持一下!下期聊聊checked exception和runtime exception
更多推荐


所有评论(0)