对于与子类相关的多个catch语句有一点很重要,即一个超类的catch语句与任何一个子类都匹配.例如,因为所有异常的超类是Throwable,所以为了捕获所有可能的异常,捕获Throwable就可以.如果既想捕获超类类型的异常,又想捕获子类类型的异常,就应该把子类放在catch语句序列的前面.否则,超类的catch语句会捕获所有派生类的异常.因为将超类放在前面会由于永远不执行子类语句而导致创建无法到达的代码(unreachable code),所以这一规则必须遵守.在Java中,创建到达的代码是一种错误.
考虑下面的程序:
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(ArrayIndexOutOfBoundsException exc) { System.out.println("No matching element found"); } catch(Throwable exc) { System.out.println("some exception occurred"); } } }
输出如下所示:
1/2=0 2/3=0 some exception occurred 4/4=1 some exception occurred 6/4=1
本例中,除了ArrayIndexOutOfBoundsException异常外,所有的异常都是由catch(Throwable)捕获的.当创建自己的异常时,捕获子类异常的问题会变得更加重要.
问:为什么要捕获超类异常?
答:原因有多个.这里说两点.首先,如果添加了一个捕获Exception类型异常的catch语句,实际上就是向异常处理程序添加了一个可以处理所有程序相关的异常语句.在无论发生什么都必须避免正常程序终止的情况下,这样的语与可能有用.其次,在某些情况下,一批异常可以被相同的语句处理.捕获这些异常的超类可以省去重复的代码.