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. Openstack_O版(otaka)部署_准备环境和依赖软件

    架构介绍 本次案列为基本的三节点部署 一:网络: 1.管理网络:192.168.198.0/24 2.数据网络:10.0.0.0/24 二:操作系统: CentOS Linux release 7.3 ...

  2. CF384 div2 E. Vladik and cards

    题意 给你一个的排列,求一个满足条件的最长子序列 每种数字的差小于等于,并且每种数字之内是连续的 解法 首先单纯认为用肯定不行的 所以应该考虑二分答案(所求长度具有二分性) 再用dp判断是否可行,这个 ...

  3. [MyBatis]DAO层只写接口,不用写实现类

    团队开发一个项目,由老大架了一个框架,遇到了DAO层不用写接口了,我也是用了2次才记住这个事的,因为自己一直都是习惯于写DAO层的实现类,所以,习惯性的还是写了个实现类.于是遇到错误了. 找不到那个方 ...

  4. (luogu P3358)最长k可重区间集问题 [TPLY]

    最长k可重区间集问题 题目链接 https://www.luogu.org/problemnew/show/3358 做法 所有点向下一个点连容量为k费用为0的边 l和r连容量为1费用为区间长度的边 ...

  5. 【BZOJ1585】【Luogu2944】地震损失2(网络流)

    [BZOJ1585][Luogu2944]地震损失2(网络流) 题面 题目描述 Wisconsin has had an earthquake that has struck Farmer John' ...

  6. 【ZJOI2008】树的统计(树链剖分)

    题面 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II ...

  7. SQL基础教程读书笔记-3

    5 复杂查询 5.1 视图 1.表和视图的区别表:保存的是实际的数据视图:保存的是SELECT语句.从视图读取数据时,视图会在内部执行该SELECT语句并创建出一张临时表. 2.视图的优点① 无需保存 ...

  8. 【经验随笔】Java程序远程调试定位特定运行环境上出现的问题

    Java后台程序远程调试 第一步:在JVM的启动参数中增加-Xdebug -Xrunjdwp:transport=dt_socket,address=6688,server=y,suspend=n 第 ...

  9. 探究c# lock

    今天早上阅读前辈的代码,看到了这么一段代码,如下所示: lock("Execute") { string sqlStr = sbSQLScript.ToString(); } 看到 ...

  10. Health Check - 每天5分钟玩转 Docker 容器技术(142)

    强大的自愈能力是 Kubernetes 这类容器编排引擎的一个重要特性.自愈的默认实现方式是自动重启发生故障的容器.除此之外,用户还可以利用 Liveness 和 Readiness 探测机制设置更精 ...