🎯 本章你会学到:受检异常为什么强制你处理,以及 try-with-resources 怎么自动关文件。建议边读边敲,每节练习先自己做,再展开答案对照。
Java 把错误处理做成了语言机制:出了问题就抛异常,必须有地方接住。好处是错误不会被默默忽略,代价是要多写几行。
抛出与捕获
抛出、捕获与 finally
public class Main {
static int divide(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("divide by zero"); // 主动抛
}
return a / b;
}
public static void main(String[] args) {
try {
System.out.println(divide(10, 2));
System.out.println(divide(1, 0)); // 这里抛出,跳到 catch
} catch (IllegalArgumentException e) { // 按类型捕获
System.out.println("caught: " + e.getMessage());
} finally {
System.out.println("done"); // 无论是否异常都会执行
}
}
}运行结果
5
caught: divide by zero
done
| 类型 | 是否强制处理 | 例子 |
|---|---|---|
| 受检异常 Exception | 必须 try-catch 或 throws 声明 | IOException、FileNotFoundException |
| 非受检 RuntimeException | 不强制,但可能运行时爆炸 | NullPointerException、ArrayIndexOutOfBounds |
| Error | 不处理(JVM 层问题) | OutOfMemoryError |
读写文件:try-with-resources
用 Files 读写文件
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException { // 也可以声明抛出
Path path = Path.of("numbers.txt");
Files.write(path, List.of("10", "20", "30")); // 写文件
int sum = 0;
for (String line : Files.readAllLines(path)) { // 读全部行
sum += Integer.parseInt(line.trim());
}
System.out.println("sum=" + sum);
}
}运行结果
sum=60
现代 Java 推荐用 java.nio.file.Files,一行读写,不用手动 close()。如果要处理大文件按行读,用 try (BufferedReader in = Files.newBufferedReader(path)) —— try-with-resources 会在退出时自动关闭资源。
⚠️ 易错点 空的
catch 块(吞异常)是最糟的写法:出了问题你什么都不知道。至少要打印日志或重新抛出。⚠️ 易错点
catch (Exception e) 放在前面会把所有异常都截住,让后面的具体捕获失效——具体异常写在前面,宽泛的写在后面。✍️ 本节练习
7.1必做安全的除法
读入两个整数,输出它们的商;如果除数为 0,输出 error(用异常处理而不是 if 判断)。
输入 一行两个整数 a b。
输出 一行:商,或 error。
样例输入
10 0样例输出
error💡 提示 用 try { ... } catch (ArithmeticException e) { ... } 捕获整数除零。
✅ 查看参考答案与解析
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
try {
System.out.println(a / b);
} catch (ArithmeticException e) {
System.out.println("error");
}
}
}解析 整数除以 0 会抛 ArithmeticException(浮点除零不会,会得到 Infinity/NaN)。
7.2挑战过滤非法输入
读入 n 行内容,能解析成整数的累加,不能解析的计数。最后输出合法数字之和与非法行数。
输入 第一行 n;接下来 n 行内容。
输出 两行:sum=和、invalid=非法行数。
样例输入
4
10
abc
20
30样例输出
sum=60
invalid=1💡 提示 Integer.parseInt(line) 失败会抛 NumberFormatException,用 try-catch 包住每一行。
✅ 查看参考答案与解析
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = Integer.parseInt(sc.nextLine().trim());
long sum = 0;
int invalid = 0;
for (int i = 0; i < n; i++) {
String line = sc.nextLine().trim();
try {
sum += Integer.parseInt(line);
} catch (NumberFormatException e) {
invalid++;
}
}
System.out.println("sum=" + sum);
System.out.println("invalid=" + invalid);
}
}解析 先 nextLine() 读掉第一行的 n(nextInt() 会把换行留在缓冲区),再逐行处理——这正是 Java 里 nextInt 与 nextLine 混用的经典坑。
📚 本文概念都在知识大全:
JVM 与字节码 · JDK · String 与 StringBuilder · 集合框架 · 泛型 · 受检异常 · 继承与接口 · record · Stream API