异常处理¶
try/catch/finally 你在 JS 里写过,Java 几乎一样。但 Java 多一个前端人完全陌生的概念:受检异常。
基本结构(和 JS 一样)¶
try {
riskyCode();
} catch (NumberFormatException e) { // 捕获特定异常
System.out.println(e.getMessage());
} finally {
cleanup(); // 无论如何都执行
}
★ 受检 vs 非受检(这是新概念)¶
| 类型 | 继承 | 特点 | 例子 |
|---|---|---|---|
| 受检异常 | Exception |
编译器强制 try/catch 或 throws,否则编译不过 | IOException、SQLException |
| 非受检异常 | RuntimeException |
和 JS 一样,可不处理 | NullPointerException、IllegalArgumentException |
// readFile 抛受检异常,下面这行不处理就编译报错:
readFile(); // ✗ Unhandled exception BizException
// 必须这样:
try { readFile(); }
catch (BizException e) { ... }
// 或者接着往上甩:
void caller() throws BizException { readFile(); }
为什么要搞受检异常
JS 的异常你忘了 catch 也不会报错,运行时才炸。Java 的受检异常让编译器逼着你面对可能出错的情况(比如 IO、数据库操作),减少了运行时意外。这是 Java"啰嗦但安全"的又一体现。
throws 和 throw¶
throw new XxxException()—— 主动抛出(对标 JSthrow)。void f() throws XxxException—— 声明"我可能抛这个异常,调用方要处理"。
自定义异常¶
业务里常用:自定义 BizException 表示"业务错误"(如余额不足),在 Spring 第三篇你会用全局异常处理器统一接住它。
完整可运行示例¶
package com.javaglm.language.ch11;
/**
* 第 09 章异常处理。
* ★ JS 没有的概念:受检异常(checked exception)。
* 继承 Exception 的异常,编译器强制你要么 try/catch 要么 throws,否则编译不通过。
* 继承 RuntimeException 的叫非受检异常,和 JS 一样可以不处理。
*/
public class ExceptionDemo {
public static void main(String[] args) {
// 1. try / catch / finally:和 JS 几乎一样
try {
int[] arr = {1, 2};
System.out.println(arr[5]); // 越界,运行时异常
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("捕获越界:" + e.getMessage());
} finally {
System.out.println("finally 无论如何都执行(对标 JS finally)");
}
// 2. 受检异常:编译器强制处理。不 try/catch 这行根本编译不过
try {
readFile();
} catch (BizException e) {
System.out.println("处理受检异常:" + e.getMessage());
}
// 3. JDK 7+ 的 multi-catch:一个 catch 抓多种异常
try {
int n = Integer.parseInt("abc");
} catch (NumberFormatException | NullPointerException e) {
System.out.println("数字格式或空指针:" + e.getMessage());
}
// 4. 主动抛出(对标 JS throw)
try {
setAge(-1);
} catch (IllegalArgumentException e) {
System.out.println("参数非法:" + e.getMessage());
}
}
/** throws 声明:告诉调用方"我可能抛这个受检异常,你必须处理"。 */
static void readFile() throws BizException {
throw new BizException("业务异常:文件不存在");
}
static void setAge(int age) {
if (age < 0) {
// RuntimeException 是非受检异常,不用 throws 声明
throw new IllegalArgumentException("年龄不能为负:" + age);
}
}
}
/** 自定义受检异常:继承 Exception。 */
class BizException extends Exception {
BizException(String msg) {
super(msg);
}
}
前端人对照¶
| JS | Java | 备注 |
|---|---|---|
try/catch/finally |
同 | 几乎一致 |
throw new Error() |
throw new XxxException() |
Java 异常是类 |
| 无受检/非受检之分 | 有 | 受检异常强制处理 |
catch (e) 抓所有 |
catch (Exception e) |
Java 要写异常类型 |
:octicons-arrow-left-16: 上一章:包与访问修饰符 | 下一章:枚举与包装类