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

原创
2012/12/16 13:59
阅读数 249

先看两段代码

// 基于异常的模式
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 收藏
0
分享
返回顶部
顶部