异常:
在程序运行过程中,出现的不正常情况叫做异常。
在解决代码中可能出现的异常,要添加非常多的逻辑来进行判断,会使代码变得非常臃肿,不利于维护,因此,推荐大家使用异常处理机制来处理程序运行过程中出现的问题。
捕获异常: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 }
情况二: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 }
情况三: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 }
情况四:将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 }
执行结果:
情况一:
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 }
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 }
异常的分类:
异常是以Throwable为顶层父类,在派生出Error类和Exception类。
Error类:这一类的错误是JVM本身的错误,一般很少出现,一旦出现就是很严重的,程序员也是处理或解决不了的;
Exception类:(由java应用程序抛出和处理的非常严重的错误)
分为检查/编译时异常(checkedException,程序必须处理该异常)和运行时异常(不要求程序员必须做出处理,但最好避免);
在Java的标准包java.lang java.util 和 java.net 中定义的异常都是非运行异常
常见的异常类型:
来源:https://www.cnblogs.com/bentuzi/p/12636981.html