
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 */
上述代码中,由于除数为零,导致程序崩溃,后面的代码都不能执行。在实际工作中,或多或少会有各种异常出现,为了尽量避免,需要引入异常的处理机制。
经过异常处理之后,代码如下
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 */
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 */
上述代码,若没有发生异常就不进入任何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 */
在实际应用中,我们可以通过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 }
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 */
加了return之后,没有执行B,但执行了A,说明不管函数有没有返回,finally部分都是要执行的。只有一种情况下,finally不会被执行,就是加了System.exit(0),表明程序到此结束。
注意:当类中方法有进行异常处理,那其子类若覆盖该方法要么不进行异常处理,要么子类中异常是父类异常的子集。
引入异常机制,可以加强程序的安全性、强健性。
来源:https://www.cnblogs.com/tiantianxiangshang33/p/4957683.html
