五分钟精通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);
    }
}

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

便于调试和处理

确保系统的健壮、可维护

相关推荐
故渊ZY2 小时前
JVM栈帧深度解析:规范与实战
java·栈帧
流绪染梦2 小时前
多表联查时处理一对多的信息,将子表字段放入数组
java·数据库
Arva .2 小时前
G1收集器
java·jvm·算法
没有bug.的程序员2 小时前
高并发电商场景:JVM资源规划实战
java·jvm·电商·资源规划
dddaidai1232 小时前
深入JVM(一):对象创建和内存分配
java·jvm
喜欢流萤吖~2 小时前
JSP 内置对象解析:功能、作用域与常用方法
java·开发语言
DKunYu2 小时前
1.Spring-Cloud初识
java·spring cloud·微服务
小坏讲微服务2 小时前
Spring Boot 4.0 + MyBatis-Plus 实战响应式编程的能力实战
java·spring boot·后端·mybatis
by__csdn2 小时前
javascript 性能优化实战:垃圾回收优化
java·开发语言·javascript·jvm·vue.js·性能优化·typescript