工作时,一直对try块中throw的异常对象,在catch中如何处理此异常,以及trycatchfinally完毕,程序是否就此停止还是继续运行很迷惑,于是参考网上的资料,自己写了些demo,去慢慢探索。
例1.
public static void main(String[] args) {
int i = 7;
int j = 0;
try {
if (j == 0)
throw new ArithmeticException();
System.out.println("打印计算结果i/j=" + i / j);
}
catch (ArithmeticException e) {
System.out.println("被除数j不能等于0");
}
System.out.println("运行结束");
}
run:
被除数j不能等于0
运行结束
结论:可以看到,当try块中创建 ArithmeticException异常对象,并由throw语句将异常抛给Java运行时系统,由系统寻找匹配的异常处理器catch并运行相应异常处理代码,打印 “被除数j不能等于0”,然后trycatch块结束,程序继续运行,打印"运行结束".可以看到,throw 异常对象,程序并未结束,而是继续执行。另外,我们在catch块中用输出语句打印信息,并不能很全面,直观,专业的把异常信息给显示出来。
例2.
public static void main(String[] args) {
int i = 7;
int j = 0;
try {
if (j == 0)
throw new ArithmeticException();
System.out.println("打印计算结果i/j=" + i / j);
}
catch (ArithmeticException e) {
e.printStackTrace();
}
System.out.println("运行结束");
}
run:
java.lang.ArithmeticException
at com.westward.Demo4.main(Demo4.java:9)
运行结束
结论:通过catch块中,调用异常对象ArithmeticException的printStackTrace()方法,能够将对应的异常信息打印出来,trycatch块下面的程序继续执行。
例3.
如果我们想在try块中,j==0时,程序抛出异常,并且程序中断,可以继续看下面的demo。
public static void main(String[] args) {
int i = 7;
int j = 0;
try {
if (j == 0)
throw new ArithmeticException();
System.out.println("打印计算结果i/j=" + i / j);
}
catch (ArithmeticException e) {
throw e;
}
System.out.println("运行结束");
}
run:
Exception in thread “main” java.lang.ArithmeticException
at com.westward.Demo4.main(Demo4.java:9)
结论:通过运行结果,我们可以看到,在catch块中throw ArithmeticException对象后,throw语句将异常抛给Java运行时系统,由系统寻找匹配的异常处理器catch,由于未找到相应的异常处理器catch(没有catch或者有catch,但是类型不符合),所以异常最后抛给了jvm,并在后台打印异常信息,程序在此中断,trycatchfinally下面的程序代码不在执行。
附加:事实上,ArithmeticException为RuntimeException(运行时异常,不可查异常)的子类。而运行时异常将由运行时系统自动抛出,不需要程序员使用throw语句显示抛出。
下两例摘自:http://blog.csdn.net/hguisu/article/details/6155636
感觉真是太经典了。
例子1:
public static void main(String[] args) {
int[] intArray = new int[3];
try {
for (int i = 0; i <= intArray.length; i++) {
intArray[i] = i;
System.out.println("intArray[" + i + "] = " + intArray[i]);
System.out.println("intArray[" + i + "]模 " + (i - 2) + "的值: "
+ intArray[i] % (i - 2));
}
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("intArray数组下标越界异常。");
} catch (ArithmeticException e) {
System.out.println("除数为0异常。");
}
System.out.println("程序正常结束。");
}
run:
intArray[0] = 0
intArray[0]模 -2的值: 0
intArray[1] = 1
intArray[1]模 -1的值: 0
intArray[2] = 2
除数为0异常。
程序正常结束。
相信很多man会和我有一样的疑问,怎么只抛出了ArithmeticException 异常,而未抛出ArrayIndexOutOfBoundsException异常呢?
答案是: 一旦某个catch捕获到匹配的异常类型,将进入异常处理代码。一经处理结束,就意味着整个try-catch语句结束。其他的catch子句不再有匹配和捕获异常类型的机会。也就是说,jvm运行.class文件遇到异常时,只会抛出一种异常,这时这个trycatch块就结束了。上例中,程序首先执行到i=2,除数为0的情况,java运行时程序将ArithmeticException 这个运行时异常抛给对应的catch异常捕捉器,执行异常代码,打印 “除数为0异常。”。然后此trycatch块结束,由于for循环在try块中,所以第4此循环不在执行。所以不会遇到 ArrayIndexOutOfBoundsException。 接着打印 “程序正常结束。”。
例子2:
public static void main(String args[]) {
int i = 0;
String greetings[] = { " Hello world !", " Hello World !! ",
" HELLO WORLD !!!" };
while (i < 4) {
try {
// 特别注意循环控制变量i的设计,避免造成无限循环
System.out.println (greetings[i]);
i++;
System.out.println(i);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组下标越界异常");
} finally {
System.out.println("--------------------------");
}
}
}
run:
会死循环。
结论:当i=3的时候,jvm执行到 System.out.println (greetings[i]);@ 会抛异常,被 ArrayIndexOutOfBoundsException捕获,执行catch块里的代码,然后执行finally,然后3<4,然后执行@处代码,然后…原因就是当System.out.println (greetings[i]);抛异常的时候,它下面的代码就不会执行了,所以i会永远等于3,3<4永远成立,进入死循环。
我们可以巧用finally如下例来避免这种情况发生。
public static void main(String args[]) {
int i = 0;
String greetings[] = { " Hello world !", " Hello World !! ",
" HELLO WORLD !!!" };
while (i < 4) {
try {
// 特别注意循环控制变量i的设计,避免造成无限循环
System.out.println (greetings[i]);
System.out.println(i);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组下标越界异常");
} finally {
System.out.println("--------------------------");
i++;
}
}
}