Java基础_学习笔记_14_异常

 1 class Test
 2 {
 3     public int devide(int x,int y)
 4     {
 5         int result=x/y;
 6         return result;
 7     }
 8 }
 9 class TestException
10 {
11     public static void main(String [] args)
12     {
13         Test t=new Test();
14         t.devide(2,0);
15         System.out.println("the program is running here!");
16     }
17 }
18 /*
19 F:\java_example\lesson61>java TestException
20 Exception in thread "main" java.lang.ArithmeticException: / by zero
21         at Test.devide(Test.java:5)
22         at TestException.main(Test.java:14)
23 */
View Code

上述代码中,由于除数为零,导致程序崩溃,后面的代码都不能执行。在实际工作中,或多或少会有各种异常出现,为了尽量避免,需要引入异常的处理机制。

经过异常处理之后,代码如下

 1 class Test
 2 {
 3     public int divide(int x,int y)
 4     {
 5         int result=x/y;
 6         return result;
 7     }
 8 }
 9 class TestException
10 {
11     public static void main(String [] args)
12     {
13         Test t=new Test();
14         try{
15             t.divide(2,0);
         System.out.println("the divide opration is over");
16 } 17 catch(Exception e) 18 { 19 System.out.println(e.getMessage()); 20 } 21 System.out.println("the program is running here!"); 22 } 23 } 24 /* 25 F:\java_example\lesson61>java TestException 26 / by zero 27 the program is running here! 28 */

在上述代码中,try的部分写入可能会发生异常的代码,异常发生后会直接转向执行catch部分代码,try中异常语句后面的代码会被忽略,如程序中的System.out.println("the devide operation is over!");语句不会被执行。整个执行流程是当try中的语句发生异常,程序会调用catch,执行完catch中的程序之后,系统会继续执行catch代码块后的其他代码。

当try代码块中的程序发生异常,系统将这个异常发生的代码行号、类别等信息封装到一个对象中,并将该对象传递给catch代码块。catch关键字后跟有一个Exception类型的参数e,这跟我们经常用到的,如何定义一个函数接收的参数格式是一样的。括号中的Exception就是try代码块传递给catch代码块的变量类型,e是变量名,也可以换成别的名称。

如果我们将catch中不写任何语句,是空的,那么当try中代码发生异常后,不会打印出任何异常信息,而很难让人觉察到程序的错误,所以这一步不能偷懒。

throws关键字

在实际工作中,代码不止是一个人编写的,前一个人编写了一个函数,另一个人需要调用,如果这个函数在调用过程中会发生异常,但是后面的人不知道,那么一场就很可能会发生并导致程序崩溃,那么我们就引入了throws关键字。写devide方法的人需要在定义该方法时加上throws 关键字,调用者在调用该方法时,加上try...catch语句进行处理。若只用throws声明,哪怕函数是正确被调用,没有写try...catch则程序编译无法通过,如下:

 1 class Test
 2 {
 3     public int divide(int x,int y) throws Exception
 4     {
 5         int result=x/y;
 6         return result;
 7     }
 8 }
 9 class TestException
10 {
11     public static void main(String [] args)
12     {
13         Test t=new Test();
14         //try{
15             t.divide(2,1);
16             System.out.println("the divide opration is over");
17         //}
18         /*catch(Exception e)
19         {
20             System.out.println(e.getMessage());
21         }*/
22         System.out.println("the program is running here!");
23     }
24 }
25 /*
26 F:\java_example\lesson61>javac Test.java
27 Test.java:15: 错误: 未报告的异常错误Exception; 必须对其进行捕获或声明以便抛出
28                         t.devide(2,1);
29                                 ^
30 1 个错误
31 */

将注释去掉之后,程序即可运行成功。

自定义异常与throw关键字

Exception类是java.lang.Throwable类的子类,Exception类继承了Throwable类的所有方法,在实际应用中,是使用Exception的子类来描述任何特定的异常。Exception类是所有异常类的父类,java中提供了常见的异常,比如:

ArithmeticException 在算术运算中发生的异常,如除数为零;

NullPointerException 空指针异常

ArrayIndexOutOfBoundsException 访问数组对象中存在的元素

除了系统定义的异常,我们也可以自己定义异常类,自定义的异常类必须继承Exception类

 1 class Test
 2 {
 3     public int devide(int x,int y) throws Exception
 4     {
 5         if(y<0)
 6             throw new DevideByMinusException("the divisor is negative "+y);
 7         //这里抛出的异常对象,就是catch(Exception e)中的e
 8         int result=x/y;
 9         return result;
10     }
11 }
12 class DevideByMinusException extends Exception
13 {
14     public DevideByMinusException(String msg)
15     {
16         super(msg);
17     }
18 }
19 class TestException
20 {
21     public static void main(String [] args)
22     {
23         Test t=new Test();
24         try{
25             t.devide(2,-1);
26             System.out.println("the devide opration is over");
27         }
28         catch(Exception e)
29         {
30             System.out.println(e.getMessage());//打印出the divisor is negative -1
31             e.printStackTrace();
32         }
33         System.out.println("the program is running here!");
34     }
35 }
36 /*
37 F:\java_example\lesson61>java TestException
38 the divisor is negative -1
39 DevideByMinusException: the divisor is negative -1
40         at Test.devide(Test.java:6)
41         at TestException.main(Test.java:25)
42 the program is running here!
43 */
View Code

java通过throw关键字抛出异常对象,语法格式是:

throw 异常对象;

一个try后面可以有多个catch,try中语句出现了哪种异常,就去执行对应的catch

 1 class Test
 2 {
 3     public int divide(int x,int y) throws ArithmeticException,DivideByMinusException
 4     {
 5         if(y<0)
 6             throw new DivideByMinusException("the divisor is negative "+y);
 7         //这里抛出的异常对象,就是catch(Exception e)中的e
 8         int result=x/y;
 9         return result;
10     }
11 }
12 class DivideByMinusException extends Exception
13 {
14     public DivideByMinusException(String msg)
15     {
16         super(msg);
17     }
18 }
19 class TestException
20 {
21     public static void main(String [] args)
22     {
23         Test t=new Test();
24         try{
25             t.divide(2,1);
26             System.out.println("the divide opration is over");
27         }
28         catch(ArithmeticException e)
29         {
30             System.out.println("Error ~ ArithmeticException");
31             e.printStackTrace();//Exception类中的方法
32         }
33         catch(DivideByMinusException e)
34         {
35             System.out.println("Error ~ DivideByMinusException");
36             e.printStackTrace();
37         }
38         catch(Exception e)
39         {
40             System.out.println(e.getMessage());//打印出the divisor is negative -1
41             e.printStackTrace();
42         }
43         System.out.println("the program is running here!");
44     }
45 }
46 /*
47 F:\java_example\lesson61>java TestException
48 Error ~ DivideByMinusException
49 DivideByMinusException: the divisor is negative -1
50         at Test.divide(Test.java:6)
51         at TestException.main(Test.java:25)
52 the program is running here!
53 */
View Code

上述代码,若没有发生异常就不进入任何catch,如果try中语句发生了异常,且该异常没有对应的catch,那么它就会执行Exception的catch,也就是我们代码中最后一个catch,因为所有的异常都是Exception的子类。也正因为如此,我们Exception对应的catch只能放在最后,如果不是放在最后,则程序编译错误,如下所示

 1 class Test
 2 {
 3     public int divide(int x,int y) throws ArithmeticException,DivideByMinusException
 4     {
 5         if(y<0)
 6             throw new DivideByMinusException("the divisor is negative "+y);
 7         //这里抛出的异常对象,就是catch(Exception e)中的e
 8         int result=x/y;
 9         return result;
10     }
11 }
12 class DivideByMinusException extends Exception
13 {
14     public DivideByMinusException(String msg)
15     {
16         super(msg);
17     }
18 }
19 class TestException
20 {
21     public static void main(String [] args)
22     {
23         Test t=new Test();
24         try{
25             t.divide(2,1);
26             System.out.println("the divide opration is over");
27         }
28         catch(Exception e)
29         {
30             System.out.println(e.getMessage());//打印出the divisor is negative -1
31             e.printStackTrace();
32         }
33         catch(ArithmeticException e)
34         {
35             System.out.println("Error ~ ArithmeticException");
36             e.printStackTrace();//Exception类中的方法
37         }
38         
39         catch(DivideByMinusException e)
40         {
41             System.out.println("Error ~ DivideByMinusException");
42             e.printStackTrace();
43         }
44         /*catch(Exception e)
45         {
46             System.out.println(e.getMessage());//打印出the divisor is negative -1
47             e.printStackTrace();
48         }*/
49         System.out.println("the program is running here!");
50     }
51 }
52 /*
53 F:\java_example\lesson61>javac Test.java
54 Test.java:33: 错误: 已捕获到异常错误ArithmeticException
55                 catch(ArithmeticException e)
56                 ^
57 Test.java:39: 错误: 已捕获到异常错误DivideByMinusException
58                 catch(DivideByMinusException e)
59                 ^
60 2 个错误
61 */
View Code

在实际应用中,我们可以通过try...catch来实现程序的跳转,下面例子中并不是真的有异常,而是我们利用try...catch的特点实现跳转

 1 void fun
 2 {
 3     try{
 4         if (x==0)
 5             throw new XxxException("Xxx");
 6         else
 7             throw new YyyException("Yyy");
 8     }
 9     catch(XxxException e)
10     {...}
11     catch(YyyException e)
12     {...}
13 }
View Code

finally关键字

使用这个关键字,在一般情况下不管程序是跳转到了哪种异常或者是没有异常,都会去执行finally中的代码块。那么问题来了,我catch后面的最后一个输出语句,也是不论有没有异常也会执行啊,何必要用一个finally呢?下面我们来看区别

 1 class Test
 2 {
 3     public int divide(int x,int y) throws ArithmeticException,DivideByMinusException
 4     {
 5         if(y<0)
 6             throw new DivideByMinusException("the divisor is negative "+y);
 7         //这里抛出的异常对象,就是catch(Exception e)中的e
 8         int result=x/y;
 9         return result;
10     }
11 }
12 class DivideByMinusException extends Exception
13 {
14     public DivideByMinusException(String msg)
15     {
16         super(msg);
17     }
18 }
19 class TestException
20 {
21     public static void main(String [] args)
22     {
23         Test t=new Test();
24         try{
25             t.divide(2,-1);
26             System.out.println("the divide opration is over");
27         }
28         catch(ArithmeticException e)
29         {
30             System.out.println("Error ~ ArithmeticException");
31             e.printStackTrace();//Exception类中的方法
32         }
33         
34         catch(DivideByMinusException e)
35         {
36             System.out.println("Error ~ DivideByMinusException");
37             e.printStackTrace();
38             return;//结束函数,有返回值的返回值,所以不会打印出B
39             //System.exit(0);//表示程序到此终止
40         }
41         catch(Exception e)
42         {
43             System.out.println(e.getMessage());//打印出the divisor is negative -1
44             e.printStackTrace();
45         }
46         finally
47         {
48             System.out.println("finally~");//A语句
49         }
50         System.out.println("the program is running here!");//B语句
51     }
52 }
53 /*
54 F:\java_example\lesson61>java TestException
55 Error ~ DivideByMinusException
56 DivideByMinusException: the divisor is negative -1
57         at Test.divide(Test.java:6)
58         at TestException.main(Test.java:25)
59 finally~
60 */
View Code

加了return之后,没有执行B,但执行了A,说明不管函数有没有返回,finally部分都是要执行的。只有一种情况下,finally不会被执行,就是加了System.exit(0),表明程序到此结束。

注意:当类中方法有进行异常处理,那其子类若覆盖该方法要么不进行异常处理,要么子类中异常是父类异常的子集。

引入异常机制,可以加强程序的安全性、强健性。

posted @ 2015-11-12 09:30  巅峰之旅  阅读(348)  评论(0编辑  收藏  举报