异常

被刻印的时光 ゝ 提交于 2020-04-05 17:29:34

异常:

               在程序运行过程中,出现的不正常情况叫做异常。

在解决代码中可能出现的异常,要添加非常多的逻辑来进行判断,会使代码变得非常臃肿,不利于维护,因此,推荐大家使用异常处理机制来处理程序运行过程中出现的问题。

捕获异常:try、catch、finally

声明异常:throws

抛出异常:throw

获取错误信息:e.printStackTrace();(常用)    e.getmessage();(不常用)

finally块:

                 在程序运行过程中,如果处理异常的部分包含finally的处理,那么无论代码是否发生异常,finally中的代码总会执行。

                  finally中包含哪些处理逻辑?

                           1、IO流的关闭操作一般设置在finally中;

                           2、数据库的连接关闭操作一般设置在finally中;

面试中常问的问题:

                  try..catch块中存在return语句,是否还执行finally块,如果执行,说出执行顺序?

情况一:try中有return,finally中没有

 1 package com.test.ExceptionQuestion;
 2 
 3 public class Demo {
 4     public static void main(String[] args) {
 5         System.out.println(test());
 6     }
 7 
 8     public static int test(){
 9         int num = 10;
10         try{
11             System.out.println("try");
12             return num += 80;//等待finally执行结束后在执行
13         }catch (Exception e){
14             System.out.println("error");
15         }finally {
16             if(num>20){
17                 System.out.println("num>20 :"+num);
18             }
19             System.out.println("finally");
20         }
21         return num;
22     }
23 }
tryCatchReturn

情况二:try和finally中均有return

 1 package com.test.ExceptionQuestion;
 2 
 3 public class Demo {
 4     public static void main(String[] args) {
 5         System.out.println(test());
 6     }
 7 
 8     public static int test(){
 9         int num = 10;
10         try{
11             System.out.println("try");
12             return num += 80;//等待finally执行结束后执行
13         }catch (Exception e){
14             System.out.println("error");
15         }finally {
16             if(num>20){
17                 System.out.println("num>20 :"+num);
18             }
19             System.out.println("finally");
20             num =100;
21             return num;
22         }
23     }
24 }
tryCatchReturn02

情况三:finally中改变返回值num

 1 package com.test.ExceptionQuestion;
 2 
 3 public class Demo {
 4     public static void main(String[] args) {
 5         System.out.println(test());
 6     }
 7 
 8     public static int test(){
 9         int num = 10;
10         try{
11             System.out.println("try");
12             return num;
13         }catch (Exception e){
14             System.out.println("error");
15         }finally {
16             if(num>20){
17                 System.out.println("num>20 :"+num);
18             }
19             System.out.println("finally");
20             num =100;
21         }
22         return num;
23     }
24 }
tryCatchReturn03

情况四:将num的值包装在Num类中

 1 package com.test.ExceptionQuestion;
 2 
 3 public class Demo {
 4     public static void main(String[] args) {
 5         System.out.println(test().num);
 6     }
 7 
 8     public static Num test(){
 9         Num number = new Num();
10         try{
11             System.out.println("try");
12             return number;
13         }catch (Exception e){
14             System.out.println("error");
15         }finally {
16             if(number.num>20){
17                 System.out.println("number.num>20 :"+number.num);
18             }
19             System.out.println("finally");
20             number.num =100;
21         }
22         return number;
23     }
24 }
25 class Num{
26     public int num = 10;
27 }
tryCatchReturn04

 

执行结果:

情况一:

try
num>20 :90
finally

90

分析:显然try的return num+=80被分成两句话1、num =num+80;2、return num;  先执行1,并把num=80保存起来,在try中的return num执行之前,先执行finally块,finally执行结束,然后在将90返回。

情况二:

try
num>20 :90
finally
100

分析:try中的return扔被分成了两句,finally中的return语句先于try中return语句的执行,所以try中的return被覆盖了,所以不再执行。

情况三:

try

finally

10

分析:虽然在finally中改变了num的值,但因为finally中并没有返回该num的值,因此在执行完finally中的语句后,test()会得到try中返回的num值,而try中的num值依然是程序进入finally前保留下来的值,因此直接返回了

情况四:

try
finally
100

从结果中可以看出,同样是在finally中改变了返回值num的值,在情况三中并没有被try中的return返回,但在这里却被try中的return语句返回了。

结论:

                 try语句再返回前,将其他所有的操作执行完,保留好要返回的值,而后转入执行finally的语句,然后分为以下三种情况:

                 1、如果finally中有return语句,则覆盖掉try中的return语句,直接执行finally中的return语句,得到返回值,这样便无法得到try中之前保留好的返回值;

                 2、如果finally中没有return语句,也没有改变要返回值,则执行完finally语句后,会接着执行try中的return语句,返回之前保留好的值;

                 3、如果finally中没有return语句,但是改变了要返回值,这里有点类似于引用传递和值传递的区别,分一下两种情况:

                            1)、如果return的数据类型是基本数据类型或者文本字符串,则在finally中对基本数据的改变不起作用,try中的return依然会返回进入finally之前保留的值;

                            2)、如果return的数据是引用数据类型,则在finally中对该引用数据类型的属性的改变是起作用的,try中的return返回的就是finally中改变后的该属性值。

 

 

        在异常情况出现的时候,可以使用try...catch...finally的方式对异常进行处理,除此之外,可以将异常向外抛出,由外部进行处理。

throws:声明异常

                在方法的调用中,可能存在多个方法之间的调用,此时如果每个方法都包含了异常情况,则需要在每个方法中都进行try...catch。另外一种比较简单的方式,就是在方法的最外层调用一次即可,使用throws方法,对所有执行过程中所有的方法出现的异常进行统一集中的处理。

                 如何判断使用try..catch还是throws?

                 最稳妥的方法是都进行异常捕获

                 偷懒的方式是判断整个调用过程中,外层的方法是否对异常进行了处理,如果处理了则直接使用throws,如果没有,则使用try...catch。

throw:抛出异常

自定义异常:

                 在java的api中提供了非常丰富的异常类,但是在某些情况下不太满足我们的需求,此时需要自定义异常

                 步骤:

                          1、继承Exception类;

                          2、需要自己定义其构造方法;

                          3、需要使用时,使用throw new  自定义异常名称;

                  什么时候使用自定义异常?

                           一般情况下不需要

                          但是在公司明确规定,或者要求异常格式规范统一的时候是必须要自定义异常。

 1 package com.test.ExceptionQuestion;
 2 
 3 public class GenderException extends Exception {
 4     public GenderException() {
 5         System.out.println("性别异常");
 6     }
 7 
 8     public GenderException(String msg) {
 9         System.out.println(msg);
10     }
11 }
GenderException
 1 package com.test.ExceptionQuestion;
 2 
 3 public class Demo {
 4     public static void main(String[] args) {
 5         try{
 6             test();
 7         }catch (GenderException e){
 8             e.printStackTrace();
 9         }finally{
10             System.out.println("欢迎光临");
11         }
12     }
13 
14     public static void test() throws GenderException{
15 
16         String gender = "111";
17         if("woman".equals(gender)){
18             System.out.println("女人");
19         }if("man".equals(gender)){
20             System.out.println("男人");
21         }else{
22             throw new GenderException("什么玩应儿。。。。");
23         }
24     }
25 }
Test

 异常的分类:

                   异常是以Throwable为顶层父类,在派生出Error类和Exception类。

                    Error类:这一类的错误是JVM本身的错误,一般很少出现,一旦出现就是很严重的,程序员也是处理或解决不了的;

                    Exception类:(由java应用程序抛出和处理的非常严重的错误)

                              分为检查/编译时异常(checkedException,程序必须处理该异常)和运行时异常(不要求程序员必须做出处理,但最好避免);

                    在Java的标准包java.lang java.util 和 java.net 中定义的异常都是非运行异常

常见的异常类型:

                     

 

 

                

 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!