摘要

本文围绕“除法运算”这一典型场景,系统介绍 Java 中方法定义、运行时异常(Unchecked Exception)与受检异常(Checked Exception)的使用,以及异常捕获的标准模式与最佳实践,帮助读者在保持代码简洁的同时,提升健壮性和可维护性。


一、方法签名与异常声明

/**
 * 计算器基础接口
 */
public interface ICalculator {
    /**
     * 将 a 除以 b 并返回商。
     * @param a 被除数
     * @param b 除数
     * @return a / b 的整数商
     * @throws ArithmeticException 当 b 为 0 时抛出(运行时异常)
     */
    int divide(int a, int b);
}
  • 访问修饰符public
  • 返回类型int
  • 方法名及参数divide(int a, int b)
  • 异常声明:运行时异常无需 throws 声明;受检异常必须在签名中添加 throws

二、示例一:直接除法(Unchecked Exception)

2.1 实现代码

public class Calculator implements ICalculator {
    @Override
    public int divide(int a, int b) {
        return a / b;  // b == 0 时抛出 ArithmeticException
    }

    public static void main(String[] args) {
        Calculator calc = new Calculator();
        System.out.println("10 ÷ 3 = " + calc.divide(10, 3));
        System.out.println("10 ÷ 0 = " + calc.divide(10, 0));
    }
}

2.2 运行结果

10 ÷ 3 = 3
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Calculator.divide(Calculator.java:4)
    at Calculator.main(Calculator.java:8)
  • 要点

    • ArithmeticException 属于 RuntimeException,编译器不强制捕获。
    • 若不在调用方捕获,程序将在运行时异常处终止。

三、示例二:安全除法(Checked Exception)

3.1 实现代码

/**
 * 安全计算器:对除零进行前置检查,并抛出受检异常
 */
public class SafeCalculator {
    /**
     * 安全除法:b 为 0 时抛出 Exception(受检异常)
     * @param a 被除数
     * @param b 除数
     * @return a / b 的整数商
     * @throws Exception 当 b 为 0 时
     */
    public int safeDivide(int a, int b) throws Exception {
        if (b == 0) {
            throw new Exception("除数不能为零");
        }
        return a / b;
    }
}

3.2 调用与异常处理

public class SafeCalculatorDemo {
    public static void main(String[] args) {
        SafeCalculator sc = new SafeCalculator();
        int[][] testCases = {{10, 2}, {10, 0}, {7, 3}};

        for (int[] tc : testCases) {
            int a = tc[0], b = tc[1];
            try {
                int result = sc.safeDivide(a, b);
                System.out.printf("%d ÷ %d = %d%n", a, b, result);
            } catch (Exception e) {
                System.err.printf("计算 %d ÷ %d 时出错:%s%n", a, b, e.getMessage());
            }
        }
    }
}

3.3 运行结果

10 ÷ 2 = 5
计算 10 ÷ 0 时出错:除数不能为零
7 ÷ 3 = 2
  • 要点

    1. 方法签名声明 throws Exception,调用方必须处理或继续抛出。
    2. 使用 throw new Exception(...) 提供业务友好的错误信息。

四、异常处理结构与模式

try {
    // 可能抛出受检或运行时异常的代码
} catch (SpecificExceptionType ex) {
    // 针对单一异常的处理逻辑
} catch (AnotherExceptionType ex) {
    // 针对另一种异常的处理逻辑
} finally {
    // 清理资源,保证执行(可选)
}
  • 多重 catch:从具体到通用,避免捕获过宽。
  • finally:用于释放资源(I/O、数据库连接等),Java 7+ 推荐使用 try-with-resources 替代。

五、最佳实践

  1. 区分异常类型

    • 受检异常 用于可预见的业务或 I/O 错误;
    • 运行时异常 用于编程错误或不应被调用者显式处理的情况。
  2. 自定义异常

    • 扩展 RuntimeExceptionException,加入错误码和上下文信息。
  3. 日志与监控

    • 捕获异常时应记录日志,必要时向上层抛出或转换为业务异常以便统一处理。
  4. 不要滥用空捕获

    catch (Exception e) {
        // 忽略异常 —— 这是反模式,容易隐藏问题
    }
    
  5. 资源管理

    • 对 I/O、数据库连接等,使用 try-with-resources 确保自动关闭。

六、总结

  • Java 仅支持值传递,无论基本类型还是引用类型,方法接收到的都是值的副本。
  • 运行时异常(Unchecked)无需声明;若不捕获,将导致程序中断。
  • 受检异常(Checked)需在方法签名中声明,调用方必须处理。
  • 合理使用 throwthrowstry–catch–finally,并结合最佳实践,可让程序既简洁健壮

掌握上述内容,将助你在 Java 开发中编写出高可用易维护的异常处理逻辑。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐