如前所述,捕获Java标准异常的附带好处是防止程序异常终止.当抛出异常时,他必须被某些代码捕获.一般来说,如果程序不捕获异常,那他就要被JVM捕获.麻烦的是JVM的默认异常处理程序会终止执行,并显示堆栈跟踪和出错信息.例如前面示例如果没有捕获异常,程序会终止运行,并显示下面的出错信息:
int nums[] = new int[10]; nums[11] = 9; Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 11 at javaTest.test2.main(test2.java:9)
尽管这样的消息对程序调试有用处,但这不是你想让别人看到的.这就是不去依赖JVM,而让程序自己处理异常之所以重要的原因所在.
如前所述,异常的类型必须与catch语句中指定的类型相符.如果不相符,异常就不会被捕获.例如,下面的程序试图用捕获ArithmeticException(另一个Java内置异常)的catch语句来捕获数组越界错误.当数组越界时,会产生一个ArrayIndexOutOfBoundsException异常,但是他不会被catch语句捕获.结果只能是导致程序异常终止.
public static void main(String args[]) { int nums[] = new int[10]; try { nums[11] = 9; } catch(ArithmeticException exc) { System.out.println("Index out of bounds!"); } }
输出如下所示:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 11 at javaTest.test2.main(test2.java:12)
正如输出说明的那样,用于捕获ArithmeticException异常的catch语句是不会捕获ArrayIndexOutOfBoundsException异常的.
异常使你能够合理的处理错误
使程序对错误做出响应,然后继续执行是异常处理的又一大好处.例如,考虑下面的程序,一个数组的元素除以另一个数组的元素.如果发生除以0的情况,就会产生ArithmeticException异常.在程序中,这个异常是通过报错错误,然后继续执行来处理的.这样,所有除以0的尝试都不会发生导致程序终止的突然的运行时错误.相反,可以合理的处理错误,使得程序继续执行.
public static void main(String args[]) { int nums[] = {1,2,3,4,5,6}; int denom[] = {2,3,0,4,0,4}; for(int i=0;i<nums.length;i++) { try { System.out.println(nums[i]+"/"+denom[i]+"="+nums[i]/denom[i]); } catch(ArithmeticException exc) { System.out.println("can't divide by zero!"); } } }
输出:
1/2=0 2/3=0 can't divide by zero! 4/4=1 can't divide by zero! 6/4=1
该例还有一点很重要:一旦处理完异常,系统就会删除他.因此,在程序中每次循环进入try代码块时,他都是崭新的,前面的任何异常都被处理过了.这样程序就可以处理重复操作了.