第七十一条:避免不必要地使用受检异常

许多Java程序员不喜欢受检异常,但是如果使用得当,它们可以改善API和程序。不同于返回码和未受检异常的是,它们强迫程序员处理异常地条件,大大地增强了可靠性。也就是说,过分使用受检异常会使API使用起来非常不方便。如果方法抛出受检异常,调用该方法的代码就必须在一个或者多个catch块中处理这些异常,或者它必须声明抛出这些异常,并让它们传播出去。无论使用哪一种方法,都给程序员增添了不可忽视的负担。这种负担在Java8中更重了,因为抛出受检异常的方法不能直接在Stream中使用(详见第45条至48条)。

如果正确的使用API并不能阻止这种异常条件的产生,并且一旦产生异常,使用API的程序员可以立即采取有用的动作,这种负担就被认为是正当的。除非这两个条件都成立,否则更适合于使用未受检异常。作为一个石蕊测试(石蕊测试是指简单而具有决定性的测试),你可以试着问自己:程序员将如何处理该异常。下面的做法是最好的吗?

} catch (TheCheckedException e) {
  throw new AssertionError(); // Can't happen!
}

下面这种做法又如何?

} catch (TheCheckedException e) { 
  e.printStackTrace(); // Oh well, we lose. 
  System.exit(1);
}

如果使用API的程序员无法做得比这更好,那么未受检的异常可能更为合适。

如果方法抛出的受检异常是唯一的,它给程序员带来的额外负担就会非常高。如果这个方法还有其他的受检异常,该方法被调用的时候,必须已经出现在一个try块中,所以这个异常只需要另外一个catch块。如果方法只抛出一个受检异常,单独这一个异常就表示:该方法必须放置于一个try块中,并且不能在Stream中直接使用。在这种情况下,应该问问自己,是否还有别的途径可以避免使用受检异常。

消除受检异常最容易的方法是,返回所要的结果类型的一个optional(详见第55条)。这个方法不抛出受检异常,而只是返回一个零长度的optional。这种方法的缺点是,方法无法返回任何额外的信息,来详细说明它无法执行你想要的计算。相反,异常则具有描述性的类型,并且能够导出方法,以提供额外的信息(详见第70条)。

“把受检异常变成未受检异常”的一种方法是,把这个抛出异常的方法分成两个方法,其中第一个方法返回一个boolean值,表明是否应该抛出异常。这种API重构,把下面的调用序列:

try { 
  obj.action(args);
} catch (TheCheckedException e) { 
  ... // Handle exceptional condition
}

重构为:

// Invocation with state-testing method and unchecked exception
if (obj.actionPermitted(args)) {
  obj.action(args); 
} else {
  ... // Handle exceptional condition 
}

这种重构并非总是恰当,但是,凡是在恰当的地方,它都会使API用起来更加舒服。虽然后者的调用序列没有前者漂亮,但是这样得到的API更加灵活。如果程序员知道调用将会成功,或者不介意由于失败而导致的线程终止,这种重构还允许以下这个更为简单的调用形式:

obj.action(args);

如果你怀疑这个简单的调用序列是否符合要求,这个API重构可能就是恰当的。这样重构之后的API在本质上等同于第69条中的“状态方法”,并且同样的告诫依然适用:如果对象将在缺少外部同步的情况下被并发访问,或者可被外界改变状态,这种重构就是不恰当的,因为在actionPermitted和action这两个调用的时间间隔之中,对象的状态有可能会发生变化。如果单独的actionPermitted方法必须重复action方法的工作,处于性能的考虑,这种API重构就不值得去做。

总而言之,在谨慎使用的前提之下,受检异常可以提升程序的可读性:如果过度适用,将会API使用起来非常痛苦。如果调用者无法恢复失败,就应该抛出未受检异常。如果可以恢复,并且想要迫使调用者处理异常的条件,首选应该返回一个optional值。当且仅当万一失败时,这些无法提供足够的信息,才应该抛出受检异常

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容