在Java中怎么选择适当的异常类

来源:Vuejs社区作者:小白龙头衔:草根站长
导读:本期聚焦于小伙伴创作的《在Java中怎么选择适当的异常类》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《在Java中怎么选择适当的异常类》有用,将其分享出去将是对创作者最好的鼓励。

Java的异常体系是所有异常处理逻辑的基础,整个体系以Throwable为顶层父类,向下分为Error和Exception两大分支。Error一般表示系统级错误,比如OutOfMemoryError,这类错误通常由JVM抛出,开发者不需要主动处理。Exception则是开发者需要重点关注的异常类型,它又分为受检异常Checked Exception和非受检异常Unchecked Exception,后者是RuntimeException及其子类。

在Java中怎么选择适当的异常类

Java异常类的核心分类

受检异常Checked Exception

受检异常是指编译器强制要求开发者处理的异常,这类异常通常是程序可以预见的、外部因素导致的错误,比如读取文件时文件不存在、网络请求时连接超时等。如果方法内部抛出了受检异常,要么在方法上声明throws抛出该异常,要么在方法内部使用try-catch块捕获处理,否则代码无法通过编译。

常见的受检异常包括IOException、SQLException、ClassNotFoundException等,这类异常的设计初衷是提醒调用方需要关注可能出现的异常情况,提前做好应对准备。

非受检异常RuntimeException

非受检异常是编译器不强制要求处理的异常,通常是程序逻辑错误导致的,比如空指针访问、数组越界、除数为0等。这类异常一般是开发者编码时的疏忽造成的,理论上可以通过完善代码逻辑避免。

常见的非受检异常包括NullPointerException、IndexOutOfBoundsException、IllegalArgumentException等,调用方可以选择处理也可以不处理,不过如果放任不管,程序运行到对应逻辑时会直接抛出错误并终止执行。

选择异常类的核心标准

判断异常是否可恢复

这是选择异常类最核心的判断依据。如果异常发生后,调用方可以通过重试、调整参数等方式让程序恢复正常执行,那么优先选择受检异常。比如调用外部接口获取数据时,出现网络超时异常,调用方可以稍后重试请求,这种情况适合用受检异常提醒调用方处理。

如果异常是程序逻辑错误导致的,发生后无法通过外部调整恢复,那么应该选择非受检异常。比如方法要求传入的参数不能为空,调用方传入了null,这种情况属于调用方的逻辑错误,抛出NullPointerException即可,不需要强制调用方处理。

判断是否是调用方的责任

如果异常的产生是因为调用方没有遵守方法的约定,比如传入了不符合要求的参数、没有提前做好前置校验,那么应该抛出非受检异常,提醒调用方修正自身的调用逻辑。比如下面的方法要求传入的年龄必须大于0,否则抛出非法参数异常:

public void setAge(int age) {
    if (age <= 0) {
        // 调用方传入非法参数,属于逻辑错误,抛出非受检异常
        throw new IllegalArgumentException("年龄必须大于0");
    }
    this.age = age;
}

如果异常的产生不是调用方的责任,而是方法内部依赖的外部资源出现问题,比如读取文件时文件被删除、连接数据库时数据库服务宕机,那么应该抛出受检异常,让调用方知晓可能出现的外部风险。

避免过度使用受检异常

受检异常虽然能强制调用方处理异常,但如果滥用会导致代码冗余。如果方法抛出的受检异常调用方根本无法处理,或者99%的调用方都会选择直接向上抛出,那么不如使用非受检异常。比如下面的场景,底层方法抛出受检异常,上层调用方只是简单向上传递:

// 底层方法抛出受检异常
public void readFile(String path) throws IOException {
    // 读取文件逻辑
}

// 上层调用方只是向上抛出,没有实际处理
public void process() throws IOException {
    readFile("test.txt");
}

这种情况使用受检异常只会增加代码负担,改成非受检异常会更合适。

自定义异常类的选择

当JDK内置的异常类无法满足业务需求时,开发者可以自定义异常类。自定义异常类时同样要遵循上述选择标准:

  • 如果自定义异常是可恢复的、需要调用方主动处理的,就继承Exception,作为受检异常使用。
  • 如果自定义异常是逻辑错误导致的、不需要强制调用方处理的,就继承RuntimeException,作为非受检异常使用。

下面是一个自定义受检异常的示例,用于表示业务中的库存不足异常,调用方收到该异常后可以提示用户补货或者调整购买数量:

// 自定义受检异常,继承Exception
public class StockNotEnoughException extends Exception {
    private int remainStock;

    public StockNotEnoughException(String message, int remainStock) {
        super(message);
        this.remainStock = remainStock;
    }

    public int getRemainStock() {
        return remainStock;
    }
}

再来看一个自定义非受检异常,用于表示订单状态不合法的逻辑错误,属于调用方没有遵守订单状态流转规则导致的:

// 自定义非受检异常,继承RuntimeException
public class InvalidOrderStatusException extends RuntimeException {
    public InvalidOrderStatusException(String message) {
        super(message);
    }
}

常见选择误区

很多开发者会陷入两个极端,要么所有异常都用受检异常,要么所有异常都用RuntimeException。前者会导致代码充斥着大量无意义的try-catch或者throws声明,降低代码可读性;后者会让调用方无法提前知晓可能出现的外部风险,增加程序运行时的不确定性。

还有开发者会把业务异常全部定义为受检异常,实际上很多业务异常是调用方参数错误导致的,比如用户传入的订单号不存在,这种情况属于调用方的逻辑问题,用非受检异常更合适。只有那些需要调用方根据异常信息做业务处理的场景,比如库存不足、余额不足,才适合用受检异常。

选择异常类的核心原则是:让异常信息准确反映问题本质,同时不给调用方增加不必要的负担。优先从JDK内置异常类中选择,内置类无法满足需求时再自定义,自定义时严格遵循可恢复性、责任归属的判断标准即可。

Java异常异常类选择RuntimeExceptionChecked_Exception异常处理修改时间:2026-07-09 06:51:33

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。