• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Java > java面试题之try中含return语句时代码的执行顺序详解

java面试题之try中含return语句时代码的执行顺序详解

作者:LiuZh 字体:[增加 减小] 来源:互联网 时间:2017-05-28

LiuZh 通过本文主要向大家介绍了try里面有return,try catch return,try return,try return finally,java try语句等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

前言

最近在刷java面试题偶然看到这类问题(try/finally中含有return时的执行顺序),觉得挺有意思于是小小的研究了一下,希望经过我添油加醋天马行空之后,能给你带来一定的帮助,下面来看看详细的介绍。

原题

try {} 里有一个return语句,那么紧跟在这个try后的finally {}里的代码会不会被执行?什么时候被执行?在return前还是后?
乍一看题目很简单嘛,java规范都说了,finally会在try代码块的return之前执行,你这文章写得没意义,不看了

你等等!(拿起我身边的五尺砍刀)

神奇栗子

看完这个栗子,你在想想执行顺序到底是怎样的

栗子代码

 public static void main(String[] args) {
 int result = test();
 System.out.println(result);
 }

 public static int test() {
 int t = 0;
 try {
 return t;
 } finally {
 ++t;
 }
 }
</div>

分析一下

test()方法内,在try中return了t,那么在main方法中test()函数的返回值应该是t=0,即控制台输出0

但是因为有finally的存在,而finally中对t进行了自增运算,并且finally会在try中的return语句之前执行,所以正确的情况是控制台输出1

所以你最终确定的答案是:控制台输出1

然而事实并非如此,将程序跑起来之后,得到的结果是:

输出0

将栗子跑起来亲眼看一下吧~

得到这个结果你也许要爆炸了,啥?java规范说的都是错的?!

不用急,到我给sun洗地的时间了

洗地时间

在洗地之前,你很有必要先理解java中的值传递,如果你已经了解该内容可略过下面这一个小节点

java中的值传递

由于这只是本文内容引申出去的知识点,不过多赘述,随便唠两句,能借此明白则好,不明白希望借助搜索引擎明白一下!
在java的方法调用中,时常需要传递参数,那么传递的参数是将之前的变量直接传递给方法内了吗?

显然不是的,调用方法传递参数的时候,传递的只是原变量的一个副本(复制体),换句话说就是,将变量的值传递给了方法体,而并没有真正的将变量传递进去。

看个栗子:

 public static void main(String[] args) {
 int t = 0;
 test(t);
 System.out.println(t);
 }

 public static int test(int a) {
 a = 111;
 }
</div>

正确输出是0,因为test()方法内拿到的a,只是t的一个副本(复制体)而并不直接是t,test()内改变了a的值,并不影响t的值

以上是对于基本数据类型,如果对于对象呢?

如果参数是对象,那么传递的是对象的引用的副本(复制体),这也就是为什么在方法体内对对象进行修改,会真正的改变对象。因为方法体外的引用和方法体内的引用指向的是堆内存中的同一个对象,传递的是对象的引用

如果这里还不能理解值传递,建议先理解一下这一个概念再继续往下看

真的开始分析了

为了你看着方便,栗子代码再来一份:(我真的不是为了凑字数)

 public static void main(String[] args) {
 int result = test();
 System.out.println(result);
 }

 public static int test() {
 int t = 0;
 try {
 return t;
 } finally {
 ++t;
 }
 }
</div>
  • 当代码执行到return t;时,并不是直接将t返回了出去,而是将t保留了起来(因为还有一个finally语句块没有执行!)并且这个保留,就是值传递性质的一个保留,也就是保留的是t的一个副本(复制体),我这里先叫他tt吧(不是套套!!)
  • 接下来执行finally语句块,finally中将t做了自增运算,t的确变成了1,但是这并没有影响t的复制体tt的值!保留起来的tt值还是0!
  • 这个时候执行完了finally,正式将保留起来的tt返回出去,于是,整个函数的返回结果就是0
  • 这个t的副本(复制体)保留的地方是哪儿呢?我查了半天,有个应该靠谱的说法,保留在函数栈中,但具体保留的区域叫什么,我也不知道,还请知情大佬指教一下!

上图或许直观一点?

那么如果,这个t是一个对象呢?按照前面说的值传递的问题,如果t是一个对象,在finally中对t进行修改,那么最终返回出去的t所显示出来的数据,应该是经过修改的。

写一个Person类来检验一下吧

public class Test {

 public static void main(String[] args) {
 Person result = test();
 System.out.println(result.age);
 }

 public static Person test() {
 Person t = new Person();
 t.age = 0;
 try {
 return t;
 } finally {
 t.age++;
 }
 }

}

class Person {
 int age;
}
</div>

这段代码输出的是1,因为Person是一个类,t是一个对象的引用,对象实例保存在堆内存中,t的副本tt也是一个对象的引用,t和tt都指向堆内存中的对象实例,那么不论修改谁,实际上对象实例都被修改了!

看完我这一通胡说八道,你应该了解了整个执行流程咯?

那么继续开一个引申

又一个小栗子

如果在finally中也有一个return,会发生什么?

 public static void main(String[] args) {
 int result = test();
 System.out.println(result);
 }

 public static int test() {
 int t = 0;
 try {
 return t;
 } finally {
 ++t;
 return t;
 }
 }
</div>

最终输出的结果是1

就是说,如果try中有return而finally中也有return,那么后者将会让前者失效!

理解

=> try中将t保留了一份副本用于返回出去,到了finally中,又有一个return语句,这时候又要创建一个用于返回的副本,那这个时候就有两个副本了,到底返回谁呢?取后者!

总结

这一个面试题,看似简单,却暗藏杀机啊!

可是说了这么多,结果就是finally在return之后执行吗?

非也,你没看见return没有真正的执行完就开始执行finally吗?并且是先执行完了finally,才执行完return,这也就很好理解java规范中的finally在return之前执行了。

不过,按如上情况,这句话应该变成这样:finally比return先执行完毕。是不是就更容易理解了呢?

也就是说,return先被执行了,执行return的时候发现有finally,于是不能那么快执行完毕return,先去执行finally,等finally执行完毕之后,return才能执行完毕。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。

</div>
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • java面试题之try中含return语句时代码的执行顺序详解
  • java面试题之try中含return语句时代码的执行顺序详解

相关文章

  • 2017-05-28Java Config下的Spring Test几种方式实例详解
  • 2017-05-28Java Collections集合继承结构图_动力节点Java学院整理
  • 2017-05-28MyBatis入门之增删改查+数据库字段和实体字段不一致问题处理方法
  • 2017-05-28SpringBoot拦截器实现对404和500等错误的拦截
  • 2017-05-28Java IO流 文件的编码实例代码
  • 2017-05-28Java 用反射设置对象的属性值实例详解
  • 2017-05-28详解springboot + profile(不同环境读取不同配置)
  • 2017-05-28spring boot如何添加拦截器
  • 2017-05-28SpringMVC实现文件的上传和下载实例代码
  • 2017-05-28深入理解java异常处理机制的原理和开发应用

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 详解Spring Boot加载properties和yml配置文件
    • Java Annotation详解及实例代码
    • Java中Object toString方法简介_动力节点Java学院整理
    • java web监听器统计在线用户及人数
    • 序列化版本号serialVersionUID的作用_动力节点Java学院整理
    • 详解 Java 中 equals 和 == 的区别
    • java 中使用匿名类直接new接口详解及实例代码
    • Linux下用java -jar运行可执行jar包的方法教程
    • Spring核心IoC和AOP的理解
    • 使用spring拦截器实现日志管理实例

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有