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

来源:互联网 发布:nginx upload pass 编辑:程序博客网 时间:2024/06/10 16:33

先看两段代码

// 基于异常的模式String t1[]={"11","22"};try{int i=0;while(true){System.out.println(t1[i]);i++;}}catch(ArrayIndexOutOfBoundsException e){}//标准模式for(String t:t1){System.out.println(t);}
为什么有人优先使用异常模式,而不是标准模式?

他们企图利用java的错误判断机制来提高性能,因为VM对每次数组访问都要检查越界情况,所以正常的终止测试被认为是多余的。这种想法有三个错误:

1.异常机制的设计初衷是用于不正常的情形,所有很少有jvm实现试图对它们进行优化,使得与显示的测试一样快速

2.把代码放在try-catch中反而阻止了现代jvm实现本来可能要执行的特定优化

3.对数组进行变量的标准模式并不会导致冗余的检查。有些现代的jvm实现会将它们优化。


基于异常的模式不仅模糊了代码的意图,降低了它的性能,而且还不能保证正常工作,例如下面的代码:

public static void main(String[] args) {String t1[]={"11","22"};try{int i=0;while(true){System.out.println(t1[i]);test();i++;}}catch(ArrayIndexOutOfBoundsException e){}}private static void test(){String t2[]={};t2[0].toString();}
使用了异常的模式,当产生了与这个bug相关的异常将会被捕捉到,并且被错误的解释为正常的循环终止条件。


设计良好的API不应该强迫它的客户端为了正常的控制流而使用异常,有两种良好的API设计

1.状态测试,指示是否可以调用这个状态相关的方法。例如,

for(Iterator<String> i=collection.iterator();i.hasNext();){     String s=i.next()}
Iterator接口有一个“状态相关”的next方法,和相应的状态测试方法hasNext().这使得利用传统的for循环对集合进行迭代的标准模式成为可能

2.如果“状态相关的”方法被调用时,该对象处于不适当的状态之中,它就会返回一个可识别的值,比如null。

如果对象将在缺少外部同步的情况下被并发访问,或者可被外界改变状态,使用可被识别的返回值可能是很有必要的。

如果单独的“状态测试”方法必须重复“状态相关”的工作,从性能的角度考虑,就应该使用可被识别的返回值。如果其他方面都是等同的,那么“状态测试”方法则略优于可被识别的返回值。

阅读全文
0 0
原创粉丝点击