← Java 学习路线(共 8 章)

第 7 章 异常与文件读写

red wenzi · 2026-09-15 · 编程语言 · Java · 📖 预计阅读 11 分钟 · 共 2 道练习
🎯 本章你会学到:受检异常为什么强制你处理,以及 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 里 nextIntnextLine 混用的经典坑。

📚 本文概念都在知识大全:

JVM 与字节码 · JDK · String 与 StringBuilder · 集合框架 · 泛型 · 受检异常 · 继承与接口 · record · Stream API