java中应杜绝“throws exception”,须声明具体受检异常(如ioexception、sqlexception)或语义化自定义异常(如insufficientstockexception),非必要场景优先使用非受检异常,并通过ide和构建工具自动化拦截裸异常声明。

Java中杜绝“throws Exception”这种裸异常声明,核心不是禁止语法,而是让开发者自然地写出语义清晰、调用方可预期的异常契约。
只声明具体受检异常类型
方法签名应明确列出实际可能抛出的受检异常,而非笼统写throws Exception。例如文件读取操作,应声明throws IOException或进一步细化为throws FileNotFoundException, SecurityException;数据库操作应声明throws SQLException。这样调用方能一眼看出需处理哪些业务相关失败场景,而不是面对一个无法决策的“黑箱”。
- 避免用
throws Exception或throws Throwable——它们掩盖了异常的真实意图 - 若一个方法确实可能抛出多种受检异常,可用多
throws并列,如throws IOException, ParseException - 不要为了省事把底层异常全部包装成自定义受检异常再统一抛出——这会稀释异常语义
用自定义受检异常替代泛型Exception
当业务逻辑存在明确的、调用方必须响应的失败路径时(如库存不足、订单已取消),应定义语义化的受检异常类,继承Exception,并在方法签名中直接声明它。例如:throws InsufficientStockException比throws Exception更能驱动调用方做针对性补偿(如提示用户、跳转补货页)。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 自定义异常名要体现业务含义,不带“Error”“Exception”冗余后缀(如用
PaymentTimeout而非PaymentTimeoutException) - 构造函数建议支持传入原始异常(
cause),保留异常链 - 避免为所有业务错误都设计受检异常——仅对“调用方有责任且有能力恢复”的场景使用
非必要不抛受检异常,优先用非受检异常
绝大多数参数校验失败、状态非法、业务规则违反等场景,应抛IllegalArgumentExceptionIllegalStateException等非受检异常。它们无需强制声明,不污染方法签名,也更符合“编程错误应尽早暴露”的原则。
- 受检异常适用于外部不可控因素(IO、网络、数据库连接),而非内部逻辑错误
- 如果某段逻辑频繁抛出受检异常且调用方总是忽略或统一兜底,说明它本不该是受检的
- Lombok的
@SneakyThrows不是解药——它掩盖问题,而非重构契约
借助工具提前拦截裸异常声明
靠人工记忆容易疏漏,应在开发流程中嵌入自动化约束:
- 在IDE(如IntelliJ)中启用检查规则:“Method declares 'throws Exception'”,设为警告或错误
- 在Maven/Gradle构建中集成Checkstyle或ErrorProne,配置规则
IllegalThrows或自定义正则匹配throws\s+Exception\b - CI流水线中设置编译阶段失败阈值,一旦检测到裸
throws Exception即阻断合并
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










