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. MFC中CFileDialog用法

    用CFileDialog选择了一个文件后,使用FILE::fopen打开文件错误,使用 的是相对地址,和王工调试了半天,怎么跟踪也没发现错误,原来如此......... CFileDialog文件选择 ...

  2. tar、scp、sftp、rsync简单使用

    tar -c 创建一个归档文件 -z 指定压缩格式为gzip -v 显示详细信息 -f 制定文件明 -j 指定压缩格式为bz2 -J 指定压缩格式为 xz -C 压缩.解压至某个目录 -x 自动识别压 ...

  3. Java并发编程笔记4-线程池

    我们使用线程的时候就去创建一个线程,但是就会有一个问题: 如果并发的线程数量非常多,而且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会导致大大降低系统的效率,因为频繁创建线程和销毁线 ...

  4. (luogu P1383)高级打字机

    高级打字机 题目链接 https://www.luogu.org/problemnew/show/P1383 背景 无聊中.. 随便在luogu上rand到了一道题 从此走上不归路 主席树是我暑假的时 ...

  5. 记一次结合PHP多进程和socket.io解决问题的经历

    公司是做棋牌游戏的.前段时间接到一个后台人工鉴定并处理通牌作弊玩家的需求,其中需要根据几个玩家的游戏ID查询并计算他们在某段时间内彼此之间玩牌输赢次数和输赢总额. 牌局数据是存储在日志中心的,他们把牌 ...

  6. php 目录处理函数

    之前我们处理的全都是文件,那目录和文件夹怎么处理呢? 我们就来学习目录或者称为文件夹的处理相关函数. 处理文件夹的基本思想如下: 1.读取某个路径的时候判断是否是文件夹 2.是文件夹的话,打开指定文件 ...

  7. 通过返回动态改变textview和imageview

    //获取并显示优惠券ID Intent intent = getIntent(); awardID=(TextView)findViewById(R.id.awardID); String id = ...

  8. Linux初学者的总结

    总算在年前把Linux的一些基本命令学完了,总结一下学到的(比较实用的)东西 我这里用的是Red Hat Enterprise Linux7的社区版本centos7 首先最重要的文件查看命令:ls.d ...

  9. MyBatis关联关系

    1.一对多:一个国家对应多个城市 01.实体类 package cn.pb.bean;import java.util.Set;/** * 国家的实体类 */public class Country ...

  10. git pull error

    在图形界面中,执行拉取操作时,出现下面的错误. You asked to pull from the remote 'origin', but did not specifya branch. Bec ...