【Java】异常
敲代码时遇到的报错、数据里突然跳脱的数值、生活中打破常规的小插曲,我们总习惯把这些 “异常” 当作麻烦。但其实,每一次异常都是系统或生活在发出信号 —— 它可能暴露了隐藏的漏洞,也可能指向新的可能性。 这篇博客想和你聊聊如何看待、应对异常,或许能让你在下次遇到 “意外” 时,多一份从容与洞察。
1.Thorwable
Java 所有异常类都直接或间接继承自 java.lang.Throwable(顶层父类),它有两个核心子类:
error:是指java虚拟机无法解决的问题,如:JVM内部错误、资源耗尽等,典型代表:stackOverflowError和OutOfMemoryError,一旦发生回力乏术,程序会直接崩溃。
Exception:程序运行时可预见、可处理的异常(如输入错误、文件不存在),是开发者关注的核心。
Exception 又分为两大类,核心区别是「是否必须显式处理」:
- 受检异常(Checked Exception):编译期强制要求处理的异常(编译器会报错),通常是外部环境导致的(如文件不存在、网络连接失败),必须通过 try-catch 捕获或 throws 声明抛出。典型代表:IOException、SQLException、ClassNotFoundException。
- 非受检异常(Unchecked Exception):编译期不强制处理的异常,通常是代码逻辑错误导致的(如空指针、数组越界),继承自 RuntimeException。
2.throw
public class ArithmeticException extends RuntimeException{public ArithmeticException() {}public ArithmeticException(String message) {super(message);}
}
自定义一个类,这个ArithmeticException继承于RuntimeException

- throw必须在方法中。
- throw抛出的对象必须是Exception或者Exception的子类的对象。
- 如果抛出的是RuntimeException或者RuntimeException的子类,也可以不处理,JVM来处理。
- 如果抛出编译器异常必须当下处理。
3.异常的捕获throws
修饰符 返回值类型 方法名() throws 异常类型、…{} 可以有多个异常类型
4.try-catch捕获并处理
throws并没有对异常进行处理,常常是将异常传给JVM,而且会告诉其方法,如果是真正要对异常进行处理的话,就要用try-catch
try{
fun(10); // 可能发生异常的方法
}catch(ArithmeticException e){
//处理异常
}catch(){} // 可以有多个catch
finally{}
注:
Exception是大部分异常的父类,都是自下而上的所以可以用Exception来兜底。
如果异常有父子关系,那么要将子写在前,父写在后.
finally不管抛出异常不,只要不在其之前程序崩溃就会执行里面的代码
5.面试题
5.1thorw和throws的区别
| 对比维度 | throw | throws |
|---|---|---|
| 核心作用 | 主动抛出「具体的异常对象」(触发异常) | 声明方法「可能会抛出」的异常类型(告知调用者) |
| 语法位置 | 方法体内部(是可执行语句) | 方法签名后(紧跟 (),是方法声明的一部分) |
| 操作对象 | 异常对象(需 new 实例,如 new NullPointerException()) | 异常类型(如 IOException、RuntimeException) |
| 数量限制 | 一次只能抛出 1 个异常对象 | 可声明多个异常类型(用逗号分隔) |
| 与受检异常关系 | 抛出受检异常时,方法必须用 throws 声明该异常(否则编译报错);抛出非受检异常(RuntimeException 子类)可不用声明 | 仅用于声明「受检异常」(编译器强制要求),非受检异常可声明也可不声明(不推荐声明) |
| 代码示例 | throw new IllegalArgumentException("参数非法"); | public void readFile() throws IOException, FileNotFoundException {} |
5.2 throw
他是手动触发异常(且在方法内执行):
throw 是「执行语句」,写在方法体里,作用是主动触发一个具体的异常(比如业务逻辑校验失败时)。
关键细节:
1.必须抛出「异常对象」(需通过 new 关键字创建,或使用已存在的异常对象);
2.抛出后,当前代码块的执行会立即中断,跳转到异常处理流程(catch 块);
3.若抛出的是「受检异常」(如 IOException),方法必须用 throws 声明该异常(否则编译报错);若抛出的是「非受检异常」(如 IllegalArgumentException),可不用声明。
5.3 throws
声明方法可能抛出的异常(方法签名后):
throws 是「方法声明的一部分」,写在方法名和参数列表之后,作用是告知调用者:该方法可能会抛出这些异常,请你处理(调用者需用 try-catch 捕获,或继续用 throws 向上抛)。
注:
1.仅声明「异常类型」,不抛出具体对象(实际抛出仍需 throw 语句);
2.可声明多个异常类型,用逗号分隔;
3.仅对「受检异常」有强制要求(编译器会检查:方法内若抛出受检异常,必须在 throws 中声明);非受检异常(RuntimeException 子类)可声明也可不声明(声明了也没错,但没必要,因为编译器不强制调用者处理)
