java中的 try、catch、finally及finally执行顺序详解:

1、首相简单介绍一下异常以及异常的运行情况:

Java中异常的继承主要有两个: Error和Exception 这两个,而Error就是jvm出现错误,以及系统奔溃等现象这些错误没办法通过程序来处理,所以在程序中不能使用catch来捕捉处理这类的异常。

对于Exception 又可以分为checkedException 和RuntimeException 这两种异常,checkedException异常在进行编译运行之前就可以知道会不会发生异常,如果不对这些异常进行抛出、捕获的话就不能通过编译。而RuntimeException就是运行的时候出现的异常在之前你是没办法确定是不是会出现异常。

异常处理过程:

把会出项异常的程序段放在try中,当抛出异常的时候就会系统会生成一个异常对象,然后进行查找捕获这个异常然后进行处理这个异常,处理之后接着执行下面的程序。

出现异常之后如果没有进行捕获处理系统就会直接将这个异常栈的跟踪信息直接打印出来之后就结束这个程序的执行。

2、为什么要用finally
先看一个没有finally的异常处理try-catch语句:
假设count为要使用到的资源,并且用完要求释放此资源。那么我们可以把释放资源的语句放到try-catch后执行,当前的程序不管是在执行完try语句块还是catch语句块,都会顺序执行到下面释放资源的语句。
int count = 0;  //初始化资源
try{
  count++;
  if(count == 1) throw new Exception("Exception in try");
}catch(Exception e){
  System.out.println("catch block");
}
count = 0; //释放资源

但是,如果在try或catch中有多条return语句,那么在每条return语句之前,都要先执行释放资源的语句:
public void f() throws Exception {
 int count = 0;  //初始化资源
 try{
   doSomething;
   statementMayCauseException;

//可能会抛出异常的语句,若异常没有被catch,则直接抛出,也不会执行到try-catch下面的语句,因为这个异常被系统处理就是打印了异常栈的信息之后就结束了这个程序,也就是结束了这个进程。
   doSomething;
   if(count == 1) throw new Exception1("E1 in try");
   if(count == 2) throw new Exception2("E2 in try");
 }catch(Exception1 e){
   count = 0; //释放资源
   throw e;  //再次把异常抛出,让上一级捕获。此时将不会执行catch外的语句,所以要先释放资源
 }catch(Exception2 e){
  count = 0; //释放资源
  return; //返回了,也不会执行catch外的语句,所以要先释放资源
 }
 count = 0;

//释放资源,其实count=0程序不会执行这里的因为在执行期间先获得了前面的那个return语句所以后面就不会执行了。
}
这样,就需要在每一个可能返回的地方,以及每一个可能出现异常而导致程序跳转的地方,考虑如何释放资源,导致复杂和冗余。

所以,需要finally语句。
把资源释放或状态还原的代码放到finally块中,可以保证在try和catch语句执行完后,一定会执行finally语句块,而不用考虑各种复杂的跳转情况。
1、int count = 0;
try{
 count++;
 if(count == 1)throw new Exception();
}catch(Exception e){
}finally{
 count = 0;
}

2.finally什么时候执行
finally在return语句之后,跳转到上一级程序之前执行。

     public class Test {  

         public static void main(String[] args) {
System.out.println(test());
} public static String test() {
try {
System.out.println("try block");
return test1();
} finally {
System.out.println("finally block");
// return "finally";
}
} public static String test1() {
System.out.println("return statement");
return "after return";
}
}

结果:
try block
return statement
finally block
after return

分析:
1.try语句块,return test1(),则调用test1方法
2.test1()执行后返回"after return",返回值"after return"保存在一个临时区域里
3.执行finally语句块。若finally语句有返回值,则此返回值将替换掉临时区域的返回值
4.再将临时区域的返回值送到上一级方法中。

try、catch、finally 这个过程也就是这样,如果try catch finally 都有return:

1、在没有异常的情况下,try 中的返回值先保存到临时区域里在去执行finally ,这个finally 有返回值,这个返回值将之前try中的保存到临时区域的值用返回的这个值替换,再将这个临时区域中的值返回给上一级方法。

2、如果有异常,则执行catch中的代码,这里的return
将返回一个返回值放到临时区域,再去执行finally ,这个finally有返回值,这样就将catch中存在临时区域中的值用这个finally
返回的值替换掉,在将这个临时区域的值返回给上一级方法。

如果finally语句有返回值,则此返回值将会替换掉临时区域原有的值。
参考:
《thinking in Java》

2,验证finally真正执行顺序

     import java.io.FileInputStream;  

     public class Test1 {
public static void main(String[] args) {
Test1 m = new Test1();
System.out.println(m.amethod());
} public int amethod() {
try {
// 1,抛出异常
FileInputStream dis = new FileInputStream("test1.txt");
} catch (Exception ex) {
// 2.catch捕获异常,并执行
System.out.println("No such file found");
// 4,return 返回
return -1;
} finally {
// 3.finally一定会在return之前执行。(准确说,应该是return;语句)
System.out.println("Done finally");
}
return 0;
}
}

输出结果为:

总结:

finally其实是仅在return
语句执行前执行,如果return一个函数,那么会先执行函数,但如果函数内有(return)语句,那么finally就会在这个return
语句前执行。finally在catch中的return之前执行但是如果catch中有返回值而finally中也有返回值的话finally中的返回值会替换catch中的返回值,因为catch中的返回值是存放在一个临时区中,try
中的过程和catch
是一样的。

如果catch块有异常向外抛出,执行顺序呢:我执行我,你抛你得异常,我finally我的语句,我俩互不干涉,你别管我啥时执行,但我一定会执行。

关于finally,此时,应该很明朗了只需记着一点:除非调用system.exit()让程序退出也就是将调用这个程序的进程断开了退出了这个程序就不会执行或断电等因素致使程序停止进程终止,否则无论任何因素finally块都一定会执行。

本文转载自 http://blog.csdn.net/qh_java/article/details/125838032017-06-0916:48:23 么么哒!!!

java中的异常以及 try catch finally以及finally的执行顺序的更多相关文章

  1. java中代码块和构造方法以及普通方法的代码执行顺序总结

    说实话,这块真的不好理解啊~都怪jvm  执行顺序搞这么复杂,哼╭(╯^╰)╮ 但是  我们能怎么办,只能研究呗!!! !:首先,毫无置疑的,静态代码块在加载时就执行了,所以肯定是最先执行的.... ...

  2. java中父类子类静态代码块、构造代码块执行顺序

    父类静态(代码块,变量赋值二者按顺序执行) 子类静态 父类构造代码块 父类构造方法 子类构造代码块 子类构造方法 普通方法在实列调用的时候执行,肯定位于上面之后了 //父类A public class ...

  3. Java中继承时静态块,构造块,构造函数的执行顺序

    public class Father { static { System.out.println("Father静态块"); } { System.out.println(&qu ...

  4. Java中的异常-Throwable-Error-Exception-RuntimeExcetpion-throw-throws-try catch

    今天在做一个将String转换为Integer的功能时,发现Integer.parseInte()会抛出异常NumberFormatException. 函数Integer.parseInt(Stri ...

  5. 【Java心得总结二】浅谈Java中的异常

    作为一个面向对象编程的程序员对于 下面的一句一定非常熟悉: try { // 代码块 } catch(Exception e) { // 异常处理 } finally { // 清理工作 } 就是面向 ...

  6. Java中的异常详解

    一.异常定义 阻止当前方法或作用域继续执行的问题,称为异常 二.异常分析      所有不正常类都继承Throwable类,这个类主要有两个子类Error类和Exception类.Error指系统错误 ...

  7. Java中的异常和处理详解

    简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户?或者用C语言风格:用函数返回值作为执行状态?. ...

  8. Java中的异常简介

    Java中异常的分类 Java中的异常机制是针对正常运行程序的一个必要补充,一般来说没有加入异常机制,程序也能正常运营,但是,由于入参.程序逻辑的严谨度,总会有期望之外的结果生成,因此加入异常机制的补 ...

  9. java中的异常类

    Java中的异常: 1. Throwable是所有异常的根,java.lang.Throwable Throwable包含了错误(Error)和异常(Exception),Exception又包含了运 ...

随机推荐

  1. 解析XML的方法

    解析XML的方法 1.DOM生成和解析XML 2.SAX生成和解析XML 3.DOM4J生成和解析XML 4.JDOM生成和解析XML

  2. C# 利用Newtonsoft.Json进行Json序列化与反序列化

    我们可以通过DataContractJsonSerializer类来序列化一个对象为json字符串. public class JsonConvert<T> { public static ...

  3. web开发性能优化---数据库篇

    1. 查询出的数据量过大(可以采用多次查询,其他的方法降低数据量),尽量采取分页查询数据 2.锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷) 3.返回了不必要的行和列 用OR的字句可以分解成 ...

  4. ajax交互数据简单拼装,数组成字符串

    json2Form:function(json) { var str = ""; for(var p in json){ // 判断对象是否为数组 if(typeof json[p ...

  5. 外网如何访问 Service?- 每天5分钟玩转 Docker 容器技术(139)

    除了 Cluster 内部可以访问 Service,很多情况我们也希望应用的 Service 能够暴露给 Cluster 外部.Kubernetes 提供了多种类型的 Service,默认是 Clus ...

  6. Struts2入门这一篇就够了

    前言 这是Strtus的开山篇,主要是引入struts框架...为什么要引入struts,引入struts的好处是什么,以及对Struts2一个简单的入门.... 为什么要引入struts? 既然Se ...

  7. mybatis快速入门(二)

    这次接着上次写增删改查吧. 现将上节的方法改造一下,改造测试类. package cn.my.test; import java.io.IOException; import java.io.Inpu ...

  8. 【ZJOI2010】网络扩容

    费用流+最大流 先一遍最大流 再所有边扩容,新加节点限制扩容量k # include <bits/stdc++.h> # define IL inline # define RG regi ...

  9. [BZOJ1385] [Baltic2000] Division expression (数学)

    Description 除法表达式有如下的形式: X1/X2/X3.../Xk 其中Xi是正整数且Xi<=1000000000(1<=i<=k,K<=10000) 除法表达式应 ...

  10. 1.3 java与C++有什么异同

    相同点: 都是面向对象的语言,都使用了面向对象的思想(封装,继承,多态等),可重用性 不同点: 1.java没有指针,避免了指针可能引起的系统问题. 2.java不支持多重继承,C++可以.但java ...