五分钟精通RuntimeException

Java异常体系

编程讲究强壮性

即确保代码在错误发生时

能按预案妥善处理

Throwable是所有异常的父级

分为两大类:Error和Exception

Error表示系统级错误

通常由JVM抛出

无法由程序处理

而Exception表示程序可处理的异常

需要程序员编码进行处理

RuntimeException

Java里异常分为受检异常和非受检异常

受检异常包括 IOException、ClassNotFoundException

这类异常可以预判到

基本上源自外部因素和环境问题

比如文件有可能读不到

类包没有引入等等

简单判断是不是受检异常

你看到IDE提示需要 try-catch 或 throws 那就是了


复杂的是RuntimeException

顾名思义

只有在运行时才能遭遇

表示程序本身有bug

例如最常见的 NullPointException

对象引用为空 或是没有初始化


到底用哪种异常是初学者最头疼的问题

简而言之

Exception 可以进行 重试、降级、中断等操作

而 Runtime 则应修复代码逻辑

举个例子

操作系统环境、网络等问题配置错误导致的

就用Exception

而Runtime都是与正在运行的代码逻辑相关的

典型Runtime

我们编写代码时会内置很多逻辑规则

当业务规则被违反时

应使用RuntimeException

典型Runtime场景如下:

复制代码
当用户输入不符合预期时,例如长度、类型不正确

当出现数据库操作逻辑错误时,例如SQL写错无法执行

当出现业务逻辑错误时

当系统内部状态不一致时

当出现无法通过外部干预解决的问题时

当需要立即终止当前操作并修复代码时

当出现系统内部bug时

当出现设计缺陷时

当需要立即修复代码而不是处理异常时

Java内置了很多Runtime的子类

根据典型场景可以选择使用

例如

复制代码
当对象未初始化时,应使用子类 NullPointerException

当出现算术错误时,例如除0,应使用子类 ArithmeticException

当出现数组索引越界时,应使用子类 IndexOutOfBoundsException

当出现类型转换错误时,应使用子类 ClassCastException

当出现并发修改异常时,应使用子类 ConcurrentModificationException

当出现数据存储不一致时,应使用子类 ArrayStoreException

当出现空指针时,应使用子类 NullPointerException

当出现参数错误时,应使用子类 IllegalArgumentException

典型Exception

对比Exception

大都是源自于外界因素

通过修改外部环境或者配置都能解决

正常情况下不应出现Exception

典型场景有:

复制代码
当需要返回错误码给前端时

当需要处理网络超时时

当需要处理数据库事务回滚时

以及常用的子类包括:

复制代码
当数据库连接失败时,应使用子类 SQLException

当文件系统操作失败时,应使用子类 IOException

当网络通信失败时,应使用子类 OException

当配置文件不存在时,应使用子类 FileNotFoundException

使用场景归纳

请不要在代码里人工补货 Runtime

例如 Controller、Service、Dao

出现 Runtime 就让他返回更高层

这样可以将异常信息反馈到 View

告诉用户,他违反了什么规则

例如:余额不足、输入为负数、手机号不是11位、没有权限等

特别在Spring项目中

采用 Runtime 就无须层层 throw

可以通过 @ControllerAdvice

在 Controller 返回给前端时

记录日志,并返回友好的错误信息给前端

同时转换为 401、500 等标准 HTTP 状态码

例如:

复制代码
/**
 * 自定义异常类
 */
public class BusinessException extends RuntimeException {
    private final String code;
    private final String traceId;

    public BusinessException(String code, String message) {
        super(message);
        this.code = code;
        this.traceId = java.util.UUID.randomUUID().toString().replace("-", "");
    }
}


@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 处理自定义业务异常
     * HTTP 400 (Bad Request)
     */
    @ExceptionHandler(value = BusinessException.class)
    public ResponseEntity<ApiResponse<Void>> handleBusinessException(BusinessException e) {
        log.warn("业务异常: code={}, message={}, traceId={}", e.getCode(), e.getMessage(), e.getTraceId());
        ApiResponse<Void> response = ApiResponse.fail(e.getCode(), e.getMessage());
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
    }

    /**
     * 处理所有未预期的系统异常 (如: NullPointerException, RuntimeException)
     * 对前端返回通用的"系统繁忙"信息,避免暴露敏感信息
     * 记录详细错误日志用于排查
     * 返回 HTTP 500
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ApiResponse<Void>> handleUnexpectedException(Exception e) {
        String traceId = java.util.UUID.randomUUID().toString().replace("-", "");
        log.error("系统内部异常 [TraceID={}]: {}", traceId, e.getMessage(), e);

        ApiResponse<Void> response = ApiResponse.fail("SYSTEM_ERROR", "系统繁忙,请稍后重试");
        response.setTraceId(traceId);

        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
    }
}

这样就能够清晰地传递错误信息

便于调试和处理

确保系统的健壮、可维护

相关推荐
非优秀程序员8 小时前
第04章 邮箱大战,163 与 QQ 的暗战|《互联网产品恩仇录》
java·vue.js·架构
知已难寻8 小时前
Docker 入门:容器技术与 Docker 基础
java·运维·服务器·docker·云原生·容器
文丑颜不良啊10 小时前
LeetCode2481~2500题目解析
java·leetcode
Flynn Liang11 小时前
同一需求三套写法:用 Spring AI、LangChain4j、AgentScope Java 各实现一个带工具调用的 RAG 助手(实战对比)
java·人工智能·大模型·架构设计·spring ai·langchain4j·agentscope
聪明的笨猪猪12 小时前
实际工程问题:AI 生成 Spring Cache(@Cacheable / @CachePut / @CacheEvict)缓存注解踩坑
java·经验分享·面试·ai编程
愿有所息12 小时前
记一次 ARM64 + JDK8 上 fastjson2 的诡异数据错乱
java
秋饼12 小时前
MCP 2026-07-28 无状态协议大改版:Spring AI 2.1 多轮往返请求与网关路由落地
java·ai·技术分享·后端开发
SL_staff14 小时前
JVS-BI 实战:业务人员如何用零代码 ELT + 可视化配置构建实时经营分析闭环
java·spring·全栈
SL_staff14 小时前
企业AI落地难?JVS-AI渐进式实践:安全可控、小切口验证、标准化沉淀与规模化复制
java·开源·aigc
SL_staff15 小时前
JVS数字底座实践:构建企业级统一内容管理平台的技术路径
java·产品