第9章 异常

来源:互联网 发布:2016怎么做好淘宝 编辑:程序博客网 时间:2024/06/02 12:35

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

try-catch滥用,其负面影响是:

  1. 异常机制初衷是针对非正常情况,所有JVM默认不对其进行优化。比如,遍历数组每次都加入try-catch,性能可能慢2倍。
  2. try-catch块,会阻止JVM对其中代码的优化
  3. 悄悄掩盖隐藏的bug

在“有状态”情况下控制异常:

  1. 提供状态测试方法:如,遍历时,提供hasNext方法,用于看是否有next元素
  2. 提供可识别的返回值:如对象处于不适当状态时,返回null(当然,不具有通用性)

 

Item 58 可恢复情况->受检异常,编程错误->运行时异常

Java提供的三种可抛出结构:

  • 受检的异常 checked exception
  • 运行时异常 runtime exception 也称未受检异常
  • 错误 error

使用受检异常还是非受捡异常,取决于:如果期望恢复,则应该使用受检异常。它们之间的区别在于:

例如在代码中写了 throw new Exception(); 和 throw new RuntimeException();  两者都会在运行期间抛出异常!

(1)但是在编译阶段前者属于抛出一个受检查异常,要求对它进行显式的try..catch捕获处理或者向上一层方法抛出,否则在编译期间就显示错误! 

(2)后者抛出是运行时异常,在编译阶段不予检查,语法上不会显示任何错误(throws处没声明不会出错,但最好声明)!

所以简单的通过throw手动抛出受检查异常和抛出运行时异常,前者要求显式处理,后者不要求作出处理。

 

Item 59 避免不必要的受检异常

石蕊测试:简单而有决定性的测试

抛出受检异常,强迫程序员处理异常,增加了编程负担

 

Item 60 优先使用标准异常

专家级程序员vs新手程序员区别之一:专家追求且通常能够实现高度的代码重用

所有错误的方法调用都可以归结为:

  1. 非法参数 IllegalArgumentException
  2. 非法状态 IllegalStateException

ConcurrentModifiedException: 如果某对象被设计为单线程或与外部同步机制配合使用,则一旦发现它被并发修改,则抛出该异常。

UnsupportedOperationException: 对象不支持所请求的操作

还有:NullPointerException  IndexOutofBoundsException

 

Item 61 抛出与抽象对应的异常

更高层的实现,应该捕获底层的异常,同时抛出可以按照高层抽象进行解释的异常 ==> 异常转译 exception translation

一种特殊的异常转译形式是:异常链 exception chaining

try{
    ...
}catch(LowerLevelException cause){
    thrownew HigherLevelException(cause);
}

 

Item 62 抛出异常要有文档

如果许多方法抛出同一异常,则为该异常建立说明,而不是逐个方法建立说明文档。

 

Item 63 细节消息中包含失败信息

要把异常细节信息和用户层次的错误信息区分开

一种做法是,在异常构造器中,考虑异常描述信息的结构

 

Item 64 努力使失败保持原子性

失败原子性 failure atomic:失败的方法调用应该使对象保持在被调用之前的状态

办法是:

  1. 设计不可变对象
  2. 对于可变对象,
    1. 在使用前进行参数检查,避免异常
    2. 调整逻辑顺序,使得任何可能会失败的计算部分都在对象状态被改变之前发生
    3. 编写一段恢复代码  主要用于永久性的数据结构(比如磁盘中)
    4. 在对象的一份临时拷贝上执行逻辑操作

 

Item 65 不要忽略异常

只要将try-catch块中catch内关闭,就忽略了异常,但建议别主动关闭报警信号