动手动脑6——异常处理
1.运行下面两端代码,观察结果:
第1段:
1 import javax.swing.*; 2 3 class AboutException { 4 public static void main(String[] a) 5 { 6 int i=1, j=0, k; 7 //k=i/j; 8 try 9 { 10 k = i/j; // Causes division-by-zero exception 11 //throw new Exception("Hello.Exception!"); 12 } 13 catch (ArithmeticException e) 14 { 15 System.out.println("被0除. "+ e.getMessage()); 16 } 17 catch (Exception e) 18 { if (e instanceof ArithmeticException) 19 System.out.println("被0除"); 20 else 21 { 22 System.out.println(e.getMessage()); 23 } 24 } 25 finally 26 { 27 JOptionPane.showConfirmDialog(null,"OK"); 28 } 29 30 } 31 }
第2段:
1 import javax.swing.*; 2 3 class AboutException { 4 public static void main(String[] a) 5 { 6 int i=1, j=0, k; 7 k=i/j; //两端代码的区别就在这里 8 try 9 { 10 k = i/j; // Causes division-by-zero exception 11 //throw new Exception("Hello.Exception!"); 12 } 13 catch (ArithmeticException e) 14 { 15 System.out.println("被0除. "+ e.getMessage()); 16 } 17 catch (Exception e) 18 { if (e instanceof ArithmeticException) 19 System.out.println("被0除"); 20 else 21 { 22 System.out.println(e.getMessage()); 23 } 24 } 25 finally 26 { 27 JOptionPane.showConfirmDialog(null,"OK"); 28 } 29 30 } 31 }
两端代码区别就在一句,但是结果并不一样:
这是第1段代码:
这是第二段代码运行结果:
结果相差很大,原因很简单,代码1中,第一次出现的 k = i / j 这句被注释掉了,所以在第二次 k = i / j 才会抛出异常,而且这个异常有catch语句来捕捉,后面还有个finally语句来输出个消息面板。而如果不加注释,也就是第二段代码,第一次出现k = i / j就会发生异常(也就是不能除0那个),由于没有捕捉机制的设置,所以JVM会自动显示异常信息(当然并不是中文啦。。),并且会结束程序。
2.阅读下面的代码,分析结果:
1 public class CatchWho { 2 public static void main(String[] args) { 3 try { 4 try { 5 throw new ArrayIndexOutOfBoundsException(); 6 } 7 catch(ArrayIndexOutOfBoundsException e) { 8 System.out.println( "ArrayIndexOutOfBoundsException" + "/内层try-catch"); 9 } 10 11 throw new ArithmeticException(); 12 } 13 catch(ArithmeticException e) { 14 System.out.println("发生ArithmeticException"); 15 } 16 catch(ArrayIndexOutOfBoundsException e) { 17 System.out.println( "ArrayIndexOutOfBoundsException" + "/外层try-catch"); 18 } 19 } 20 }
由于实在内层发生的异常,内层的catch语句捕捉后直接处理掉
3.修改了上面的代码,分析下面的结果:
1 public class CatchWho2 { 2 public static void main(String[] args) { 3 try { 4 try { 5 throw new ArrayIndexOutOfBoundsException(); 6 } 7 catch(ArithmeticException e) { 8 System.out.println( "ArrayIndexOutOfBoundsException" + "/内层try-catch"); 9 } 10 throw new ArithmeticException(); 11 } 12 catch(ArithmeticException e) { 13 System.out.println("发生ArithmeticException"); 14 } 15 catch(ArrayIndexOutOfBoundsException e) { 16 System.out.println( "ArrayIndexOutOfBoundsException" + "/外层try-catch"); 17 } 18 } 19 }
由于在内层的try中没有对ArrayIndexOutOfBoundsException这类异常进行处理的语句,所以这个异常会被抛出,而外层catch语句可以捕捉这类异常,所以最后输出结果会显示外层那一堆。
3.运行下面的代码,分析结果:
1 public class EmbededFinally { 2 3 4 public static void main(String args[]) { 5 6 int result; 7 8 try { 9 10 System.out.println("in Level 1"); 11 12 13 try { 14 15 System.out.println("in Level 2"); 16 // result=100/0; //Level 2 17 18 try { 19 20 System.out.println("in Level 3"); 21 22 result=100/0; //Level 3 23 24 } 25 26 catch (Exception e) { 27 28 System.out.println("Level 3:" + e.getClass().toString()); 29 30 } 31 32 33 finally { 34 35 System.out.println("In Level 3 finally"); 36 37 } 38 39 40 // result=100/0; //Level 2 41 42 43 } 44 45 catch (Exception e) { 46 47 System.out.println("Level 2:" + e.getClass().toString()); 48 49 } 50 finally { 51 52 System.out.println("In Level 2 finally"); 53 54 } 55 56 // result = 100 / 0; //level 1 57 58 } 59 60 catch (Exception e) { 61 62 System.out.println("Level 1:" + e.getClass().toString()); 63 64 } 65 66 finally { 67 68 System.out.println("In Level 1 finally"); 69 70 } 71 72 } 73 74 }
这个例子比较简单,整形除0抛出异常被捕捉,输出字符串形式的异常信息,该执行的finally块中的语句正常执行
4.finally语句一定会执行吗?当然不一定,如果catch捕捉异常之后执行了System.exit(0)这类结束程序的语句,finally自然不会执行。
比如下面这个例子:
1 public class SystemExitAndFinally { 2 3 4 public static void main(String[] args) 5 { 6 7 try{ 8 9 10 System.out.println("in main"); 11 12 throw new Exception("Exception is thrown in main"); 13 14 //System.exit(0); 15 16 17 } 18 19 catch(Exception e) 20 21 { 22 23 System.out.println(e.getMessage()); 24 25 System.exit(0); 26 27 } 28 29 finally 30 31 { 32 33 System.out.println("in finally"); 34 35 } 36 37 } 38 39 40 }
结果显然易见,in finally 是不会被输出的
5.关于跟踪异常的传播路径:
以下代码仅供参考:
1 // UsingExceptions.java 2 // Demonstrating the getMessage and printStackTrace 3 // methods inherited into all exception classes. 4 public class PrintExceptionStack { 5 public static void main( String args[] ) 6 { 7 try { 8 method1(); 9 } 10 catch ( Exception e ) { 11 System.err.println( e.getMessage() + "\n" ); 12 e.printStackTrace(); 13 } 14 } 15 16 public static void method1() throws Exception 17 { 18 method2(); 19 } 20 21 public static void method2() throws Exception 22 { 23 method3(); 24 } 25 26 public static void method3() throws Exception 27 { 28 throw new Exception( "Exception thrown in method3" ); 29 } 30 }
运行结果:
6.一个抛出多个所谓“受控异常”的例子":
1 import java.io.*; 2 public class ThrowMultiExceptionsDemo { 3 public static void main(String[] args) 4 { 5 try { 6 throwsTest(); 7 } 8 catch(IOException e) { 9 System.out.println("捕捉异常"); 10 } 11 } 12 13 private static void throwsTest() throws ArithmeticException,IOException { 14 System.out.println("这只是一个测试"); 15 // 程序处理过程假设发生异常 16 throw new IOException(); 17 //throw new ArithmeticException(); 18 } 19 }
运行结果:
7.子类抛出受控异常的限制:一个子类的throws子句抛出的异常,不能是其基类同名方法抛出的异常对象的父类。
下面的这个例子可以说明这个问题:
1 import java.io.*; 2 3 4 public class OverrideThrows 5 { 6 public void test()throws IOException 7 { 8 FileInputStream fis = new FileInputStream("a.txt"); 9 } 10 } 11 class Sub extends OverrideThrows 12 { 13 //如果test方法声明抛出了比父类方法更大的异常,比如Exception 14 //则代码将无法编译…… 15 public void test() throws FileNotFoundException 16 { 17 //... 18 } 19 }
注释上给出了具体说明。
8.最后我也来写一个简单的例子吧:
编写一个程序,此程序在运行时要求用户输入一个 整数,代表某门课的考试成绩,程序接着给出“不及格”、“及格”、“中”、“良”、“优”的结论。
要求程序必须具备足够的健壮性,不管用户输入什 么样的内容,都不会崩溃。
代码如下:
1 import java.util.InputMismatchException; 2 import java.util.Scanner; 3 4 public class Test { 5 @SuppressWarnings("resource") 6 public static void main(String[]a) { 7 int num = 0; 8 Scanner input = new Scanner(System.in); 9 10 try { 11 System.out.print("输入数学分数:"); 12 num = input.nextInt(); 13 if(num<0||num>100)throw new NumberFormatException(); 14 } 15 catch(NumberFormatException e) { 16 //如果输入的是越界数字,直接抛出这个格式异常 17 System.out.println("输入有误!"); 18 input.close(); 19 System.exit(-1); 20 } 21 catch(InputMismatchException e) { 22 //如果输入的不是整形,而是double或者String等类型,会直接抛出这个异常 23 System.out.println("输入有误!"); 24 input.close(); 25 System.exit(-1); 26 } 27 if(num<60)System.out.println("数学不及格"); 28 else if(num>=60&&num<=69)System.out.println("数学及格"); 29 else if(num>=70&&num<=79)System.out.println("数学中等"); 30 else if(num>=80&&num<=89)System.out.println("数学良好"); 31 else if(num>=90&&num<=99)System.out.println("数学优秀"); 32 else System.out.println("数学满分"); 33 input.close(); 34 } 35 }
附上几次验证结果:
输入字符串(字符):
输入小数:
输入越界数字(小于0或者大于100):
最后小小的骄傲一下(P.S.:我数学确实还可以的说。。。):
----------------------------------------------------------------------------------------------
END