Java异常机制与 finally 与return的关系;
来源:互联网 发布:mac有道词典离线词库 编辑:程序博客网 时间:2024/06/06 12:36
异常机制是指当程序出现错误后,程序如何处理。当出现错误后,程序执行的流程发生改变,程序的控制权转移到异常处理器。
Java异常体系图:
Throwable 类是 Java 语言中所有错误或异常的超类。上图是网上比较常见的一种图,给出了我们常见的几个异常;
- Error:
Error表示程序在运行期间出现了十分严重、不可恢复的错误,在这种情况下应用程序只能中止运行,例如JAVA 虚拟机出现错误。Error是一种unchecked Exception,编译器不会检查Error是否被处理,在程序中不用捕获Error类型的异常。一般情况下,在程序中也不应该抛出Error类型的异常。
- Checked Exception异常:
Checked Exception异常(上图中的粉色异常),所有继承自Exception 并且不是RuntimeException 的异常都是checked Exception,上图中的 IOException 和 ClassNotFoundException。JAVA 语言规定必须对checked Exception作处理,编译器会对此作检查,要么在方法体中声明抛出(throws)checked Exception,要么使用catch语句捕获checked Exception进行处理,不然不能通过编译。
- RuntimeException异常:
RuntimeException 是一种Unchecked Exception,即表示编译器不会检查程序是否对RuntimeException作了处理,在程序中不必捕获RuntimException类型的异常,也不必在方法体声明抛出RuntimeException类。RuntimeException发生的时候,表示程序中出现了编程错误,所以应该找出错误修改程序,而不是去捕获RuntimeException。
异常处理的流程
- 遇到异常,方法立即结束,同时,抛出一个异常对象,并不会返回一个值;
- 调用该方法的程序也不会继续执行下去,而是搜索一个可以处理该异常的异常处理器,并执行其中的代码;
几点说明:
1、两种异常都可以捕获
运行时异常表示无法让程序恢复运行的异常,导致这种异常的原因通常是由于执行了错误的操作。一旦出现错误,建议让程序终止。
受检查异常表示程序可以处理的异常。要么 try 要么 throws,否则调用会出错,连编译也无法通过。当然,这两种异常都是可以通过程序来捕获并处理的,例如:
public static int testNoFinally1(){ int b = 20; int c=0; try { c = b/0;//这里抛出了运行时异常 System.out.println("try block"); return b += 80; } catch (Exception e) { System.out.println("catch block"); } finally { System.out.println("finally block"); } System.out.println("after catch /0"); return c; }
输出结果:
catch blockfinally blockafter catch /00
2、异常处理的语法规则:
- try语句不能单独存在,可以和
catch,finally
组成try...catch...finally
、try...catch
、try...finally
三种结构,catch语句可以有一个或多个,finally语句最多一个,try、catch、finally这三个关键字均不能单独使用。 - try、catch、finally 三个代码块中变量的作用域分别独立而不能相互访问。如果要在三个块中都可以访问,则需要将变量定义到这些块的外面。
- 多个catch块时候,Java虚拟机会匹配其中一个异常类或其子类,就执行这个catch块,而不会再执行别的catch块。
- throw语句后不允许有紧跟其他语句,因为这些没有机会执行。编译都通不过;
- 如果一个方法调用了另外一个声明抛出异常的方法,那么这个方法要么处理异常,要么声明抛出。
3、 throw和throws关键字的区别
throw用来抛出一个异常,在方法体内。语法格式为:throw 异常对象。
throws用来声明方法可能会抛出什么异常,在方法名后,语法格式为:throws 异常类型1,异常类型2…异常类型n。
4、子类重写父类的方法时候不能声明抛出比父类大的异常
当我们子类要重写父类中的方法,如果父类的方法有异常声明,那么子类重写这个方法时候,所要声明的异常不应该比父类的大。只能是小等,或者可以没有。
Return 与 Finally
以下两种情况 finally 语句是不会被执行的:
(1)try语句没有被执行到,如在try语句之前就返回了比如在try之前抛出了异常,这样finally语句就不会执行,这也说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到。
(2)在try块中有System.exit(0);这样的语句,System.exit(0);是终止Java虚拟机JVM的,连JVM都停止了,所有都结束了,当然finally语句也不会被执行到。
Finally语句的执行与return的关系:不知道finally语句是在try的return之前执行还是之后执行?
答: finally 语句是在 try 的 return 语句执行之后 (return expression 中 expression表达式执行之后),return返回之前 (return返回expression结果之前)执行。
1. finally语句在return语句执行之后 return返回之前执行的。
public static int testFinalReturn1() { int b = 20; try { System.out.println("try block"); //这个return 可以分两步 第一计算 b+=80; 第二步:返回 结果100; //在执行完第一步时,回去执行finally里面的东西,然后再执行第二步; //如果是return 100这样的表达式,可以把第一步看中100=100也会在执行完finally的东西执行返回; return b += 80; } catch (Exception e) { System.out.println("catch block"); } finally { System.out.println("finally block"); //由于第一步b+=80使得b=100所以这个判断肯定会执行 if (b > 25) { System.out.println("b>25, b = " + b); //b=b-30; //不建议代码,我们在finally主要是做释放资源和善后的结果; //如果我们在这里修改了b的值 不会影响到return的b=100的结果, } } return b; }
输出结果:
System.out.println(testFinalReturn1());try blockreturn statementfinally blockafter return
2. finally块中的 return 语句会覆盖 try 块中的 return 返回;
public static int testFinalReturn2() { int b = 20; try { System.out.println("try block"); return b += 80; } catch (Exception e) { System.out.println("catch block"); } finally { System.out.println("finally block"); if (b > 25) { System.out.println("b>25, b = " + b); b=b-30; //不建议代码,我们在finally主要是做释放资源和善后的结果; } return b;//这里的return语句会覆盖上面return语句的第二步所以b=100-30, } //return b; }
输出结果:
System.out.println(testFinalReturn2());try blockfinally blockb>25, b = 10070
注意: 这说明finally里的return直接返回了,就不管try中是否还有返回语句,finally里加上return过后,finally外面的return b就变成不可到达语句了,也就是永远不能被执行到,所以需要注释掉否则编译器报错;
3. 在finally中对return expression中的expression值进行修改是否会影响到return的返回值;
3.1 对于基本类型及其包装类不会修改其原始值
public static int testFinalReturnModify1() { int b = 20; try { System.out.println("try block"); //在此Step1 b=100, Step2 return 100; return b += 80; } catch (Exception e) { System.out.println("catch block"); } finally { System.out.println("finally block"); if (b > 25) { System.out.println("b>25, b = " + b); } //对b的值进行了修改;不会影响到原来值, b = 150; } //由于上面已在Step2中返回来了这里就不会再执行; return 2000; }
输出结果:
System.out.println(testFinalReturnModify1());try blockfinally blockb>25, b = 100100
public static Integer testFinalReturnModify2() { Integer b = new Integer(20); Integer c = new Integer(80); try { System.out.println("try block"); //在此自动拆箱Step1 b=100, Step2 return 100; return b += c; } catch (Exception e) { System.out.println("catch block"); } finally { System.out.println("finally block"); if (b > 25) { System.out.println("b>25, b = " + b); } //对b的值进行了修改;不会影响到原来值, b = 150; } //由于上面已在Step2中返回来了这里就不会再执行; return 2000; }
输出结果
System.out.println(testFinalReturnModify2());try blockfinally blockb>25, b = 100100
3.2 对于String 类型不会修改其原始值,但是在finally执行完再进行拼接;
public static String testFinalReturnModify4() { String str = "hello"; try { System.out.println("try block"); //这个比较特殊,限制性finally 在进行拼接返回; return str+" world"; } catch (Exception e) { System.out.println("catch block"); } finally { System.out.println("finally block"); System.out.println("str = " + str);//hello if ("hello world".equals(str)) {//false System.out.println("str = " + str); } //对 str 的值进行了修改;不会影响到原来值, str = "abc"; } //由于上面已在Step2中返回来了这里就不会再执行; return "def"; }
输出结果:
System.out.println(testFinalReturnModify4());try blockfinally blockstr = hellohello world
3.3 对于引用 类型会修改其原始值:
public static Map testFinalReturnModifyRef(){ Map<String, String> map = new HashMap<String, String>(); //在此对KEY赋予初始值 INIT; map.put("KEY", "INIT"); try { map.put("KEY", "TRY"); return map; } catch (Exception e) { map.put("KEY", "CATCH"); } finally { map.put("KEY", "FINALLY"); //将这个引用赋为 null; map = null; } return map; }
输出结果:
System.out.println(testFinalReturnModifyRef());{KEY=FINALLY}
static class Student{ private String name; private int age; public Student(){} public Student(String name,int age){ this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } } public static Student testFinalReturnModifyRef2(){ Student stu = new Student("zhangsan",30); //在此对KEY赋予初始值 INIT; try { return stu; } catch (Exception e) { System.out.println("catch.."); stu.setName("catch"); } finally { System.out.println("finally -->"+stu ); System.out.println("finally.."); //编译不通过 意思是说这个stu不可以访问; stu.setName("finally"); } return stu; }
输出结果:
finally -->Student [name=zhangsan, age=30]finally..Student [name=finally, age=30]
4. try块里的return语句在异常的情况下不会被执行,这样具体返回哪个看情况。
public static int test4() { int b = 20; try { System.out.println("try block"); b = b / 0;//抛出运行时异常 //下面这个语句不会再执行,而是直接执行处理完异常以后的语句; return b += 80; } catch (Exception e) { b += 15; System.out.println("catch block: b+=15 ->" + b); } finally { System.out.println("finally block"); if (b > 25) { System.out.println("b>25, b = " + b); } b += 50; } //处理完异常以后,从异常处理完结束的地方继续往下执行: return 204; }
输出结果:
System.out.println(test4());try blockcatch block: b+=1535finally blockb>25, b = 35204
5. 当发生异常后,catch中的return执行情况与未发生异常时try中return的执行情况完全一样。
public static int test5() { int b = 20; try { System.out.println("try block"); //抛出异常 b = b /0; //下面这个语句用于执行不了了; return b += 80; } catch (Exception e) { System.out.println("catch block"); //step 1 b=20+15 step2 return 35; return b += 15; } finally { System.out.println("finally block"); if (b > 25) { System.out.println("b>25, b = " + b); } //不会影响到上面的35; b += 50; } //这里执行不到,不需要写 编译不通过; //return b; }
输出结果:
System.out.println(test5());try blockcatch blockfinally blockb>25, b = 3535
在此特别鸣谢以下前辈给出的经验和知识的分享;
Java常见的异常小结:
异常的深入研究与分析:
Java异常体系详解:
Java finally语句到底是在return之前还是之后执行 重点感谢
- Java异常机制与 finally 与return的关系;
- java 中try catch finally 与return位置的关系
- java return 与 finally
- java中的try中的return与finally执行顺序关系
- Java异常时,finally 与return 执行顺序
- Java finally 和 return 的关系
- java中try catch finally与return的执行顺序
- java中finally与return的执行顺序详解
- Java 中 finally块与return语句的返回顺序
- java中return与finally的执行顺序
- Java中finally块与return之间的执行顺序
- Java中finally与return的执行顺序
- java中finally与return的执行顺序详解
- java异常处理机制finally中的return返回
- java面试之finally与return
- finally与return执行循序 Java
- Java中,finally与return执行问题
- finally与return
- win10下python3.6安装numpy,scipy,matplotlib
- 数据结构上机实验三:二叉树
- python 多进程
- 上机练习题——接口
- 第十周java作业--异常
- Java异常机制与 finally 与return的关系;
- 机器学习(一):SVM
- Qt第一个问题:Could not create directory
- K:NAT原理与NAT穿越
- Blog16@linux存储设备的管理(1)—挂载
- Python入门笔记
- 初学HTTP
- jdbc访问数据库详解
- 3.Less变量