温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何优雅处理Java异常

发布时间:2026-07-26 09:48:56 来源:亿速云 阅读:89 作者:小樊 栏目:编程语言

在 Java 中,“优雅处理异常”的核心目标是:让程序健壮、可维护、可读,同时不掩盖问题、不滥用异常机制。下面从设计原则、实践技巧和常见误区三个层面系统讲解。


一、核心原则(先有认知)

1. 异常只用于“异常场景”

❌ 不要用异常做正常流程控制:

// 错误示例
try {
    int value = map.get(key);
} catch (NullPointerException e) {
    value = defaultValue;
}

✅ 正确做法:

Integer value = map.get(key);
if (value == null) {
    value = defaultValue;
}

2. 区分“可恢复”和“不可恢复”异常

类型 示例 处理方式
可恢复 用户输入错误、网络重试 catch 后处理
不可恢复 空指针、OOM、系统错误 抛出或记录后终止

二、异常设计层面(优雅的基础)

1. 自定义异常要有意义

不要一个项目只有 RuntimeException

✅ 推荐:

public class OrderNotFoundException extends RuntimeException {
    public OrderNotFoundException(String orderId) {
        super("Order not found: " + orderId);
    }
}

✅ 如果是可恢复异常:

public class PaymentFailedException extends Exception {}

2. 使用异常链(保留根因)

永远不要吃掉原始异常

❌ 错误:

catch (SQLException e) {
    throw new RuntimeException("DB error");
}

✅ 正确:

catch (SQLException e) {
    throw new RuntimeException("DB error", e);
}

三、代码层面的优雅实践

1. 精确捕获异常(不要 catch Exception)

❌ 不推荐:

try {
    ...
} catch (Exception e) {
    e.printStackTrace();
}

✅ 推荐:

try {
    ...
} catch (IOException | SQLException e) {
    log.error("业务失败", e);
}

2. 早 throw,晚 catch

  • 在问题发生的地方抛
  • 在能处理的地方 catch
public void processOrder(Order order) throws OrderInvalidException {
    if (order == null) {
        throw new OrderInvalidException("order is null");
    }
}
try {
    processOrder(order);
} catch (OrderInvalidException e) {
    // 统一处理
}

3. 使用 finally / try-with-resources

✅ 自动关闭资源(强烈推荐):

try (BufferedReader br = new BufferedReader(new FileReader(file))) {
    return br.readLine();
}

❌ 不要手动关闭资源(容易漏)


4. 统一异常处理(Web 项目)

Spring Boot 示例

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(OrderNotFoundException.class)
    public Response<Void> handle(OrderNotFoundException e) {
        return Response.error(404, e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public Response<Void> handle(Exception e) {
        log.error("系统异常", e);
        return Response.error(500, "系统异常");
    }
}

✅ 优点:

  • 业务代码干净
  • 异常集中管理
  • 返回结构统一

四、日志与异常一起处理

1. 不要只打印,不记录

e.printStackTrace();

log.error("支付失败,orderId={}", orderId, e);

2. 不要重复记录异常

catch (Exception e) {
    log.error("error", e);
    throw e; // 上层还会再记一次
}

✅ 要么记录,要么抛出,不要都做。


五、常见反模式(一定要避免)

❌ 1. 空 catch

catch (Exception e) {
    // ignore
}

❌ 2. 用异常做 if-else

try {
    return list.get(0);
} catch (IndexOutOfBoundsException e) {
    return null;
}

❌ 3. 捕获 Throwable

catch (Throwable t) { }

六、一个“优雅处理异常”的示例

public void createUser(User user) {
    if (user == null) {
        throw new IllegalArgumentException("user is null");
    }

    try {
        userRepository.save(user);
    } catch (DuplicateKeyException e) {
        throw new BusinessException("用户已存在", e);
    }
}

七、一句话总结

优雅处理 Java 异常 = 精准抛、合理捕、保留原因、统一处理、不滥用。

如果你愿意,我可以:

  • 结合你当前项目(Spring / 普通 Java)给具体示例
  • 对比 Checked vs Unchecked Exception 的最佳实践
  • 帮你设计一套异常与返回码规范
向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI