Java 实例 – 使用 catch 处理异常(建议收藏)

Java 实例 – 使用 catch 处理异常

在 Java 编程中,异常处理是保障程序稳定运行的重要机制。当程序遇到不可预期的情况,比如除以零、文件不存在、数组越界等,Java 会抛出异常。如果这些异常不被妥善处理,程序就会崩溃。而 catch 块正是我们用来“捕获”并“处理”异常的关键工具。

想象一下:你正在驾驶一辆车,前方突然出现一个坑洼。如果你没有刹车系统(即异常处理机制),车辆可能直接翻车。而 catch 就像是你的刹车系统——它能让你在发现问题时及时减速、停稳,避免事故。今天我们就通过几个真实场景的 Java 实例,深入理解如何使用 catch 处理异常。


异常是什么?为什么需要处理?

在 Java 中,异常(Exception)是运行时错误的表示。它不同于编译错误,编译错误在代码写好时就能发现,而异常是程序运行过程中才发生的。

举个例子:当你写一段代码试图除以零:

int result = 10 / 0;

这行代码在编译时没有问题,但运行时会抛出 ArithmeticException,程序直接中断。这就像你按下了“启动”按钮,但发动机突然熄火——你无法继续前进。

为避免这种“突然熄火”,我们需要用 try-catch 结构来捕获异常,让程序在出错时优雅地处理,而不是崩溃。


基本语法结构:try-catch 的工作方式

try-catch 是 Java 异常处理的基础结构。它的逻辑是:

  • try 块:放可能抛出异常的代码。
  • catch 块:紧跟在 try 后,用来“捕获”并处理特定类型的异常。

语法如下:

try {
    // 可能发生异常的代码
} catch (异常类型 变量名) {
    // 处理异常的代码
}

实例 1:处理除零错误

public class DivisionExample {
    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        int result;

        // 尝试执行除法操作
        try {
            result = a / b;
            System.out.println("计算结果是:" + result);
        } catch (ArithmeticException e) {
            // 捕获除零异常
            System.out.println("错误:不能除以零!");
            System.out.println("异常信息:" + e.getMessage());
        }

        System.out.println("程序继续执行,没有崩溃!");
    }
}

输出结果:

错误:不能除以零!
异常信息:/ by zero
程序继续执行,没有崩溃!

关键点

  • ArithmeticException 是除法中除以零时抛出的异常类型。
  • e 是异常对象,可以通过 e.getMessage() 获取详细的错误描述。
  • catch 块执行后,程序不会中断,而是继续向下运行。

多种异常类型如何处理?

一个 try 块中可能引发多种异常。此时,我们可以使用多个 catch 块,按顺序处理不同类型的异常。

实例 2:处理多种可能的异常

import java.util.Scanner;

public class InputHandler {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("请输入一个整数:");
        String input = scanner.nextLine();

        try {
            // 尝试将字符串转换为整数
            int number = Integer.parseInt(input);
            // 尝试执行除法
            int result = 100 / number;
            System.out.println("计算结果是:" + result);

        } catch (NumberFormatException e) {
            // 处理输入不是数字的情况
            System.out.println("错误:输入的不是有效数字!");
            System.out.println("请确保输入的是整数。");

        } catch (ArithmeticException e) {
            // 处理除以零的情况
            System.out.println("错误:除数不能为零!");
            System.out.println("请重新输入一个非零的整数。");

        } finally {
            // 无论是否发生异常,都会执行
            scanner.close();
            System.out.println("扫描器已关闭。");
        }
    }
}

运行结果示例:

  • 输入:abc
    输出:错误:输入的不是有效数字!

  • 输入:0
    输出:错误:除数不能为零!

📌 说明

  • NumberFormatException:当 Integer.parseInt() 无法解析字符串时抛出。
  • catch 块的顺序很重要:父类异常应放在最后,否则子类异常会被“提前捕获”。
  • finally 块:无论是否发生异常,都会执行,常用于关闭资源。

异常处理的常见场景与最佳实践

在实际开发中,catch 处理异常不仅仅是为了“不让程序崩溃”,更是为了提供更好的用户体验和系统可维护性。

场景 1:文件读取操作

import java.io.*;

public class FileReadExample {
    public static void main(String[] args) {
        String filename = "data.txt";

        try (FileReader fr = new FileReader(filename);
             BufferedReader br = new BufferedReader(fr)) {

            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }

        } catch (FileNotFoundException e) {
            System.out.println("文件未找到:" + filename);
            System.out.println("请检查文件路径是否正确。");

        } catch (IOException e) {
            System.out.println("读取文件时发生错误:" + e.getMessage());
            System.out.println("可能是文件损坏或权限不足。");

        } // 自动关闭资源(try-with-resources)
    }
}

优势

  • 使用 try-with-resourcesFileReaderBufferedReader 会自动关闭,避免资源泄漏。
  • FileNotFoundExceptionIOException 的子类,因此必须先捕获它,再捕获父类。

异常处理的误区与避坑指南

很多初学者在使用 catch 时容易犯几个错误,以下是常见的坑:

常见错误 问题说明 正确做法
catch (Exception e) 捕获所有异常 太宽泛,可能隐藏真正的问题 明确捕获具体异常类型
catch 中打印 e.printStackTrace() 仅用于调试,生产环境不推荐 使用日志框架如 Log4j
忽略 finally 块中的资源释放 导致内存或文件句柄泄漏 使用 try-with-resources
catch 块为空 看似“处理”了异常,实则无意义 至少输出错误信息或记录日志

💡 小贴士
catch 块不是“万能解药”。如果异常无法处理,应该重新抛出(throw e)或记录日志后继续向上抛。


异常链与自定义异常(进阶)

在复杂系统中,我们可能需要创建自己的异常类型,以便更清晰地表达业务逻辑。

自定义异常类示例

// 自定义异常类:年龄无效
class InvalidAgeException extends Exception {
    public InvalidAgeException(String message) {
        super(message);
    }
}

使用自定义异常

public class AgeValidator {
    public static void checkAge(int age) throws InvalidAgeException {
        if (age < 0 || age > 150) {
            throw new InvalidAgeException("年龄必须在 0 到 150 之间!");
        }
        System.out.println("年龄有效:" + age);
    }

    public static void main(String[] args) {
        int[] testAges = {-5, 25, 200};

        for (int age : testAges) {
            try {
                checkAge(age);
            } catch (InvalidAgeException e) {
                System.out.println("验证失败:" + e.getMessage());
            }
        }
    }
}

输出:

验证失败:年龄必须在 0 到 150 之间!
年龄有效:25
验证失败:年龄必须在 0 到 150 之间!

价值

  • 自定义异常让代码更具可读性和可维护性。
  • 结合 catch,能精准定位业务问题。

总结与建议

通过今天的分享,我们深入实践了 Java 实例 – 使用 catch 处理异常 的核心用法。从基础的除零错误,到多异常处理、文件读取、自定义异常,我们一步步构建了完整的异常处理思维。

记住几个关键原则:

  1. 尽早捕获异常:不要让程序“裸奔”。
  2. 精准捕获:优先捕获具体异常类型,避免 Exception 通吃。
  3. 合理处理:不要忽略异常,至少记录或提示用户。
  4. 资源管理:使用 try-with-resources 自动释放资源。
  5. 日志替代打印:生产环境用日志框架代替 printStackTrace()

异常处理不是“写完就完事”的技术,而是系统健壮性的基石。掌握 catch 的使用,是你从初级开发者迈向中级工程师的重要一步。

在你今后的 Java 项目中,不妨主动为关键操作加上 try-catch。你会发现,程序不再轻易“崩掉”,而是在风雨中依然稳健前行。