Effective Java读书笔记二十(Java Tips.Day.20)

来源:互联网 发布:app流程图制作软件 编辑:程序博客网 时间:2024/05/22 07:42

TIP 57 只针对异常的情况才使用异常


异常应该只用于异常的情况下。它们永远不应该用于正常的控制流。


状态测试方法

在设计API时,如果类具有“状态相关”的方法,即只有在特定的不可预知的条件下才可以被调用的方法,这个类往往也应该编写一个“状态测试”方法,即指示是否可以调用这个状态相关的方法。

例如,Iterator接口有一个状态相关的方法:next(),和相应的状态测试方法:hasNext()。于是客户端可以方便的使用传统循环对集合进行迭代。如果不编写hasNext方法,迭代循环就不得不catch一个NoSuchElementException 异常,并以此来结束循环。

可识别的返回值

如果状态相关的方法调用时,对象恰好处于不适当的状态中,它就返回一个可识别的值,比如null。

例如,Iterator 的next方法可以返回一个null,客户端可以对此识别之后,结束迭代循环。


总之,异常是为了在异常情况下使用而设计的。不要将它们用于普通的控制流,也不要编写迫使客户端这么做的API。


TIP 58 对可恢复的情况使用受检异常,对编程错误使用运行时异常


如果期望调用者能够适当的恢复程序运行,对于这种情况,就应该使用受检的异常。


用户可以抛出的三种结构:

  • 受检的异常
    在使用受检的异常时,在catch字句中做恢复处理,或者记录程序运行日志。
    在设计API时,在方法中声明要抛出的每个受检的异常,这样可以提醒客户端在使用该方法时,必须使用try-catch字句。

  • 未受检的异常
    用于表示编程错误。大多数的此类异常都表示前提违例。例如数组越界异常,除0异常等等。对于此类异常,无需进行任何处理。如果程序因此而中断,则应仔细检查代码,并修正编程错误。
    永远不要为了程序的健壮性,而使用try-catch字句来catch此类异常

  • 错误
    往往被JVM保留用于表示资源不足、约束失败,或者其他程序无法继续执行的条件。比如加载本地so库失败。
    对于错误,程序员可以参考未受检的异常来处理。


简而言之,不要让应用程序的正确性依赖于线程调度器。
否则,既不健壮,也不具有可移植性。


TIP 59 避免不必要地使用受检的异常


在设计API时,不要过度地使用受检的异常。


具体的办法是,把抛出异常的方法分成两个方法,其中第一个方法返回boolean,表明是否应该抛出异常。

如果正常的使用异常:

try {     object.action(param);}catch (TheCheckedException exception){     //处理异常情况}

现在,我们给object新增一个状态测试方法:actionPermitted,用于判断对象是否处于合适的状态,那么,在调用action时,就可以这样做:

if (object.actionPermitted(param)){    object.acton(param);}else {    //处理异常情况}

显然,抛弃了try-catch代码,可以使API一直处于正常的程序流下,客户端使用API更灵活。


这种重构在下面情况下是不应该的:如果对象在缺少外部同步的情况下被并发访问,或者可被外界改变状态。这种重构不是线程安全的。

原创粉丝点击