对Java的Exception的思考

对Java Exception的思考

背景

在对接项目设计接口时,对异常设计通常疑问:

  1. 为什么抛出的异常都是Runtime的异常? 什么时候应该用Checked Exception
  2. 读接口要不要抛出业务异常?
  3. 异常何时捕获最佳?

要回答这一系列问题,并不是一个容易的事情,且听我娓娓道来。

两种异常

我们通常在概念上将异常分为Checked ExceptionRuntime Exception这两种异常,那么接下来我们来看看两种异常的层级图。在网上有很多的层级图是这样子的:
在这里插入图片描述

但真正在代码的时候却是这样的:
在这里插入图片描述
在代码中并没有一个CheckedException的class,或者说Exception就是CheckedException。

明白了异常的层级结构,那么我们来看看两种异常使用上的区别。

Checked Exception必须明确捕获进行处理,如果不捕获,那么就会编译的时候报错。
RuntimeException则不然,这个异常是无需明确捕获的,是在运行时进行检查的。

那么接下来我们看一下为什么都这么分?或者这么分的好处是什么?

这里要引经据典了,我比较赞同Effective Java书中的一个建议方式:

Item 58: Use checked exception for recoverable conditions and runtime exceptions for programming errors

使用CheckedException来表示可以恢复的异常,使用RuntimeException来表示编程出的问题。

但是回到真实的情况里,却发现情况往往不是这样的。我们的微服务接口通常都是抛出的RuntimeException,RPC解耦层也不抛出CheckedException,这是为什么呢? 这样子是对的吗?

回到现实

面对上面的问题,我不禁陷入了沉思。道理归道理,现实归现实的吗?

在分布式的经典理论中,微服务都被认为是不可靠的,所以我们不更应该去捕获去做处理,去重试吗? 等等,重试?

想到重试的时候,感觉抓到了什么,在微服务的调用框架中,往往都会提供重试的能力,也就是说虽然没有用单个微服务没有声明CheckedException,但是框架总是认为它会出错的,所以进行了捕获并且进行了重试,所以也是间接起到了checked exception的作用,符合理论上讲的”可恢复的资源建议捕获进行重试“。而且微服务的调用也比较特殊,通常都是通过反射调用,所以微服务接口抛不抛CheckedException本身并不重要。不过对于微服务来讲,大部分的场景是需要立即返回的,做资源重试直到恢复往往是不现实的,基本上超过了几秒钟后,用户已经不再当前页面进行等待了,所以在配置重试的时候要很谨慎才可以。

接下来看RPC的接口。我们的RPC接口通常都不会抛CheckedException,这说到底本质上还是重试的必要性和价值问题,和上面微服务考虑的是一样的,而且框架都已经做了重试,没有必要做相同的处理了。使用RuntimeException的好处是是流程变得简单,统一在出口处进行捕获处理就可以。

总结下来,对于资源类的服务,需要捕获异常且重试,建议是使用CheckedException明确告诉调用方进行捕获。

总结完了,让我们来回答一下开篇的问题。

解决问题

  1. 为什么抛出的异常都是Runtime的异常? 什么时候应该用Checked Exception
    资源类的建议都抛CheckedException,如果在框架有重试的情况下,可以选择不抛,由框架进行处理。
  2. 读接口要不要抛出业务异常?
    建议都走Result,不仅明确,而且能够减少序列化的成本。Java语言的异常堆栈构建一次还是比较耗费资源的。
  3. 异常什么时候捕获?
    异常有两个作用: 提供阻断信号 和 阻断信息。我们如果可以通过处理阻断进行自动处理,就可以在需要的时候进行捕获;如果需要阻断的信息,依赖来说要遵守两个原则: 边界隔离和延迟捕获的原则。边界隔离是指将工作内容隔离的地方进行捕获并转化,成为内部统一可以理解的错误;延迟捕获是指在真正需要的地方进行处理,而不必每一层都进行处理。

参考资料:

  1. Effective Java
  2. 如何优雅的处理异常
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值