You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编译器与JVM如何识别RuntimeException为非受检异常起点?

编译器对RuntimeException的识别逻辑

编译器在编译阶段直接基于继承关系判定异常类型:

  • 检查异常类型的继承链时,只要该异常是RuntimeException(或其子类)、Error(或其子类),就会被标记为非受检异常,不需要强制要求用try/catch捕获,也不用在方法上通过throws声明;
  • 要是异常属于Exception的子类,但既不是RuntimeException体系也不是Error体系,就会被判定为受检异常,必须处理。

这个规则是Java语言规范(JLS)明确规定的,像javac这类编译器的类型检查模块里,直接内置了这个判断逻辑——说白了就是编译时对异常类型做继承关系校验,判断它是否属于RuntimeException或Error的分支。

JVM对非受检异常的运行时处理

JVM在运行时对受检和非受检异常的处理流程基本一致:

  1. 异常抛出时,JVM从当前栈帧开始,向上逐个查找匹配的catch块;
  2. 找到匹配的块就执行对应的处理逻辑;
  3. 如果遍历完所有栈帧都没找到处理块,就终止当前线程,打印异常栈轨迹。

两者的差异只在编译阶段的约束,JVM运行时不会额外区分,只是非受检异常通常是程序逻辑错误导致的,编译时没强制处理,所以更容易在运行时暴露。

Java层面的规范实现

Java没有用额外的代码标记来区分受检/非受检异常,完全靠继承体系+语言规范来实现:

  • RuntimeException本身是Exception的子类,但JLS直接规定它和它的子类属于非受检范畴;
  • 标准库中的非受检异常(比如NullPointerException、ArrayIndexOutOfBoundsException)都直接或间接继承自RuntimeException;
  • 自定义非受检异常时,只要让类继承RuntimeException就行,编译器会自动识别,不需要额外注解或标记。

举个自定义非受检异常的简单例子:

public class CustomRuntimeException extends RuntimeException {
    public CustomRuntimeException(String msg) {
        super(msg);
    }
}

使用这个异常时,既不用在方法上写throws CustomRuntimeException,也不用强制try/catch,编译器不会报错。

内容的提问来源于stack exchange,提问作者Manuel Jordan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 00:29:57