文档章节

finally与return之间的关系

jiangmitiao
 jiangmitiao
发布于 2015/09/02 09:08
字数 1346
阅读 91
收藏 3

定论

问:finally语句一定会执行吗?

答:

1.如果没有执行相应的try语句则不会执行。

2.在try语句中如果调用System.exit(0)方法则不会执行。

 

问:finally会在什么时候执行?

答:如果在try/catch语句中调用转移指令例如:return,break,continue,throw等。则会在转移指令前执行。

 

总结

finally与return之间的关系

如果在finally中含有return语句,那么try/catch语句的return还有作用吗?

先看一段代码:

/**
 * Created by gavin on 15-9-2.
 */
public class FinallyTest {
    public static void main(String[] args){
        System.out.println(test1());    //3
        System.out.println(test2());    //3
        System.out.println(test3());    //2
        System.out.println(test4());    //2
    }
    public static int test1()
    {
        int i = 1;
        try {
            i = 2;
            return i;
        }finally {
            i++;
            return i;
        }
    }
    public static int test2()
    {
        int i = 1;
        try {
            i = 2;
            return i;
        }finally {
            i = 3;
            return i;
        }
    }
    public static int test3()
    {
        int i = 1;
        try {
            i = 2;
            return i;
        }finally {
            i++;
        }
    }
    public static int test4()
    {
        int i = 1;
        try {
            i = 2;
            return i;
        }finally {
            i = 3;
        }
    }
}

如果你对java内存布局不是很清楚,请看这篇文章:java虚拟机类加载机制和字节码执行引擎 http://my.oschina.net/jiangmitiao/blog/483824

重点关注运行时栈帧结构(局部变量表槽,操作数栈)。

上边的代码非常简单,来看一下字节码指令吧

public static int test1();
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=3, args_size=0
         0: iconst_1      	//定义一个常量1入栈到操作数栈	        
         //栈1	0:	1:
         1: istore_0      	//出栈,存储到局部便量表槽0	        
         //栈	0:1	1:
         2: iconst_2      	//定义一个常量2入栈到操作数栈	        
         //栈2	0:1	1:
         3: istore_0      	//出栈,存储到局部变量表槽0	        
         //栈	0:2	1:
         4: iload_0       	//从局部便量表槽0入栈到操作数栈	
         //栈2	0:2	1:
         5: istore_1      	//出栈,存储到局部变量表槽1	        
         //栈	0:2	1:2
         6: iinc          0, 1	//局部变量表槽0变量加1		        
         //栈	    0:3	1:2
         9: iload_0       	//从局部变量表槽0入栈到操作数栈	
         //栈3	0:3	1:2
        10: ireturn       	//结束,返回			                        
        //栈3	0:3	1:2
        11: astore_2      
        12: iinc          0, 1
        15: iload_0       
        16: ireturn       
  
  public static int test2();
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=3, args_size=0
         0: iconst_1      	//定义一个常量1入栈到操作数栈	
         //栈1	0:	1:
         1: istore_0      	//出栈,存储到局部便量表槽0	
         //栈	        0:1	1:
         2: iconst_2      	//定义一个常量2入栈到操作数栈	
         //栈2	0:1	1:
         3: istore_0      	//出栈,存储到局部变量表槽0	
         //栈	        0:2	1:
         4: iload_0       	//从局部变量表槽0入栈            	
         //栈2	0:2	1:
         5: istore_1      	//出栈,存储到局部变量表槽1	
         //栈	        0:2	1:2
         6: iconst_3      	//定义一个常量3入栈                	
         //栈3	0:2	1:2
         7: istore_0      	//出栈,存储到局部便量表槽0	
         //栈	        0:3	1:2
         8: iload_0       	//从局部变量表槽0入栈            	
         //栈3	0:3	1:2
         9: ireturn       	//结束,返回			                
         //栈3	0:3	1:2
        10: astore_2      	
        11: iconst_3      
        12: istore_0      
        13: iload_0       
        14: ireturn       
   
  public static int test3();
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=3, args_size=0
         0: iconst_1      	//定义一个常量1入栈到操作数栈	
         //栈1	0:	1:
         1: istore_0      	//出栈,存储到局部便量表槽0	
         //栈	        0:1	1:
         2: iconst_2      	//定义一个常量2入栈到操作数栈	
         //栈2	0:1	1:
         3: istore_0      	//出栈,存储到局部变量表槽0	
         //栈        	0:2	1:
         4: iload_0       	//从局部变量表槽0入栈            	
         //栈2	0:2	1:
         5: istore_1      	//出栈,存储到局部变量表槽1	
         //栈        	0:2	1:2
         6: iinc          0, 1	//局部变量表槽0变量加一		
         //栈	        0:3	1:2
         9: iload_1       	//从局部变量表槽1入栈            	
         //栈2	0:3	1:2
        10: ireturn       	//结束,返回			                
        //栈2	0:3	1:2
        11: astore_2      
        12: iinc          0, 1
        15: aload_2       
        16: athrow        
  
  public static int test4();
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=3, args_size=0
         0: iconst_1      	//定义一个常量1入栈到操作数栈	
         //栈1	0:	1:
         1: istore_0      	//出栈,存储到局部便量表槽0	
         //栈        	0:1	1:
         2: iconst_2      	//定义一个常量2入栈到操作数栈	
         //栈2	0:1	1:
         3: istore_0      	//出栈,存储到局部变量表槽0	
         //栈        	0:2	1:
         4: iload_0       	//从局部变量表槽0入栈            	
         //栈2	0:2	1:
         5: istore_1      	//出栈,存储到局部变量表槽1	
         //栈        	0:2	1:2
         6: iconst_3      	//定义一个常量3入栈到操作数栈	
         //栈3	0:2	1:2
         7: istore_0      	//出栈,存储到局部变量表槽0	
         //栈        	0:3	1:2
         8: iload_1       	//从局部变量表槽1入栈            	
         //栈2	0:3	1:2
         9: ireturn       	//结束,返回			                
         //栈2	0:3	1:2
        10: astore_2      
        11: iconst_3      
        12: istore_0      
        13: aload_2       
        14: athrow

我们看到,在finally中没有return时,栈中最后存储的数据是try/catch中操作后数据。即finally操作后的数据存储到其他槽中,而后再加载try/catch操作后的数据。

而在finally中含有return时,栈中最后存储的数据是finally中操作后的数据。即finally操作后的数据存储到其他槽中,而后加载的是其他槽(finally)中的数据。

 

也就是说:如果finally中不含有return语句,finally对try/catch操作的八大基础类型不会再加载到操作数栈中。

如果返回值是对象引用,finally中的return还有待考据。

 

参考:关于 Java 中 finally 语句块的深度辨析 http://www.ibm.com/developerworks/cn/java/j-lo-finally/

 

更多文章:http://blog.gavinzh.com

© 著作权归作者所有

共有 人打赏支持
jiangmitiao

jiangmitiao

粉丝 19
博文 52
码字总数 52336
作品 1
朝阳
程序员
私信 提问
【Java】疯狂Java基础(二)——final, finally, finalize 的区别

一、前言 这次说说final、finally、finalize这三者的区别,其实对这三者有了解的程序员,基本都知道,他们三个之间没有毛线关系。就是因为名字相似,其他的什么也没有。 二、final final可以...

kisscatforever
2018/03/29
0
0
java 中的finally 语句块执行顺序

参考博文1:https://www.ibm.com/developerworks/cn/java/j-lo-finally/ 参考博文2:http://www.cnblogs.com/lanxuezaipiao/p/3440471.html 网上有很多人探讨Java中异常捕获机制try...catch......

Oscarfff
2016/04/26
66
0
Java基础知识拾遗补缺

最近要换工作,明天就要去面试,还是长沙一家不错的公司,赶紧看看面试蹄,查漏补缺,希望可以通过面试。 这里先记录下复习过程中碰到的知识点,主要是自己感觉很重要又不记得的。 一个数的正...

梅岭泳者
2015/12/17
23
0
Java finally语句与return语句执行顺序解析

网上有很多人探讨Java中异常捕获机制try...catch...finally块中的finally语句是不是一定会被执行?很多人都说不是,当然他们的回答是正确的,经过我试验,至少有两种情况下finally语句是不会...

passionfly
2015/04/18
0
0
Android源码分析------SQLiteDatabase(1)

看了SQLiteDatabase的replace接口的源码,感觉写的很好,有些可以借鉴的地方,记录如下: public long replace(String table, String nullColumnHack, ContentValues initialValues) { try ...

亭子happy
2013/12/20
0
1

没有更多内容

加载失败,请刷新页面

加载更多

table边框样式

table{ border:0.5px solid #000; border-collapse:collapse; //去除边框间空隙}th,td{ border:0.5px solid #000;}...

学霸猫
9分钟前
1
0
分布式消息通讯Kafka原理分析(二)

本章重点: 1.消息的存储原理2.Partition的副本机制原理3.副本数据同步原理 消息的文件存储机制 通过如 下命令找到对应partition下的日志内容 [root@localhost ~]# ls /tmp/kafka-logs/f...

须臾之余
14分钟前
0
0
Vue Element表单绑定(四)常用操作整理

一、启用回车提交报单操作 在登录页面,使用回车提交表单操作一般是必要的一个操作。在 Element中如何使用呢,示例如下: 来个注意点: 1.button按钮的native-type设置为submit,而不是绑定c...

tianma3798
18分钟前
1
0
《大话数据结构》读后总结(七)

常见的时间复杂度 执行次数 函数阶 非正式术语 12 O(1) 常数阶 2n+3 O(n) 线性阶 3n^2+2n+1 O(n2) 平方阶 5log2n+20 O(logn) 对数阶 2n+3nlog2n+19 O(nlogn) nlogn阶 6n^3+2n^2+3n+4 O(n3) 立...

徐曙辉
20分钟前
0
0
three.js 事件交互

点击查看交互效果 在three.js中,展示的一切内容都是在canvas中绘制的,所以点击事件点击到物体上是无法获取点击对象的,要获取点击的对象要使用RayCaster,用于在三维空间中进行鼠标拾取,原...

tianyawhl
20分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部