关于try...catch...finally中return的疑惑
关于try...catch...finally里面的return一直是面试的一个热门考点。无非就分以下几个情况:
1、当有finally语句并且try中有return,在执行到return(还未执行)的时候,会先执行finally里面的内容,然后再执行行try中的return。
package com.and.java.demo;
public class 测试 {
public static void main(String[] args) {
System.out.println(new 测试().test());
}
public String test() {
try {
System.out.println("try{...}");
return "try";
} catch (Exception e) {
System.out.println("catch{...}");
return "catch";
} finally {
System.out.println("finally{...}");
}
}
}
输出:
try{...}
finally{...}
try
2、在1的基础上,如果finally里面也有return语句,则try代码块中的return被屏蔽(不执行),即在try中遇到return的时候,会先执行finally里面的内容(包括finally里面的return语句)。
package com.and.java.demo;
public class 测试 {
public static void main(String[] args) {
System.out.println(new 测试().test());
}
public String test() {
try {
System.out.println("try{...}");
return "try";
} catch (Exception e) {
System.out.println("catch{...}");
return "catch";
} finally {
System.out.println("finally{...}");
return "finally";
}
}
}
输出:
try{...}
finally{...}
finally
遇到的问题:
这两种情况想必大家已经掌握。但是还有一种情况,也是我不能理解的地方。一般情况下,在finally里面作一些数据的关闭操作(比如文件,输入/输出流,数据库的关闭),试想一下,要是我们在finally里面对要返回的值进行修改,那会反应到最终的结果上去吗?(因为从上面的讲解可以知道,当try里面有return的时候,它不会立刻执行,会先执行finally里面的内容,然后再执行return)。
package com.and.java.demo;
public class 测试 {
public static void main(String[] args) {
System.out.println(new 测试().test());
}
public String test() {
String result = "";
try {
result = "try";
return result;
} catch (Exception e) {
result = "catch";
return result;
} finally {
result = "finally";
}
}
}
试想一下,它会输出"try" 呢还是"finally"呢?
输出:
try
确实只输出try,但是我们在finally里面是改变了result的值呀?
再进一步改进,判断finally里面的赋值语句是否执行
package com.and.java.demo;
public class 测试 {
public static void main(String[] args) {
System.out.println(new 测试().test());
}
public String test() {
String result = "";
try {
result = "try";
return result;
} catch (Exception e) {
result = "catch";
return result;
} finally {
System.out.println("t1->"+result);
result = "finally";
System.out.println("t2->"+result);
}
}
}
输出:
t1->try
t2->finally
try
从输出结果可以看出,finally里面的赋值语句是执行了的,但是在return结果中怎么就没变呢?(目前暂时研究到这个地步,仍没搞明白,还望各位高手指点)
你的最后一句我不赞同,再看下面代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public
class
测试 {
int
i =
0
;
public
static
void
main(String[] args) {
测试 t =
new
测试();
System.out.println(t.i);
System.out.println(t.test());
System.out.println(t.i);
}
public
int
test() {
try
{
i =
1
;
return
i;
}
catch
(Exception e) {
i = -
1
;
return
i;
}
finally
{
i =
2
;
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public
class
测试 {
public
static
void
main(String[] args) {
System.out.println(
new
测试().test());
}
public
String test() {
String result =
""
;
try
{
result =
"try"
;
return
result;
}
catch
(Exception e) {
result =
"catch"
;
return
result;
}
finally
{
System.out.println(
"t1->"
+result);
result =
"finally"
;
System.out.println(
"t2->"
+result);
//在这里加上一行,就会看到返回值变了
return
result;
}
}
}
|
在
try{
s ="a";
return s;
}catch{
s="b";
return s;
}finally{
s ="c";
}
结构中虚拟机的处理方式是 在try 语句中 会把return的变量引用的对象存入一个局部变量表(虚拟机可见,程序不可见)里面,然后进入finally语句块中,如果finally没有return语句,则处理finally的语句,这个时候finally的变量S和Try中的变量S是同一个变量,所以S的值是改变的。但是finally执行结束之后,return 返回值的时候,会把复制的结果返回
例如下面的代码
public class TryCatchFinally {
@SuppressWarnings("finally")
public Test test() {
Test t = new Test();
try {
t.setS("try");
return t;
} catch (Exception e) {
//result = "catch";
return t;
} finally {
t = new Test();
t.setS("finallyu");
//return result;
}
}
}
class Test{
public String s ="a";
public void setS(String s){
this.s = s;
}
}
其实还是返回的 Test.getS() 结果为 try
try{
s ="a";
return s;
}catch{
s="b";
return s;
}finally{
s ="c";
}
结构中虚拟机的处理方式是 在try 语句中 会把return的变量引用的对象存入一个局部变量表(虚拟机可见,程序不可见)里面,然后进入finally语句块中,如果finally没有return语句,则处理finally的语句,这个时候finally的变量S和Try中的变量S是同一个变量,所以S的值是改变的。但是finally执行结束之后,return 返回值的时候,会把复制的结果返回
例如下面的代码
public class TryCatchFinally {
@SuppressWarnings("finally")
public Test test() {
Test t = new Test();
try {
t.setS("try");
return t;
} catch (Exception e) {
//result = "catch";
return t;
} finally {
t = new Test();
t.setS("finallyu");
//return result;
}
}
}
class Test{
public String s ="a";
public void setS(String s){
this.s = s;
}
}
其实还是返回的 Test.getS() 结果为 try
我知道为什么了。博主所说的,try代码块中的return被屏蔽(不执行),是错误的,不会被屏蔽,仍然执行,屏蔽的仅仅是跳转指令。
package com.and.java.demo;
public class 测试 {
public static void main(String[] args) {
System.out.println(new 测试().test());
}
public String test() {
try {
System.out.println("try{...}");
return "try";
} catch (Exception e) {
System.out.println("catch{...}");
return "catch";
} finally {
System.out.println("finally{...}");
return "finally";
}
}
}
分析以上代码,先执行try中的return语句,该语句会将"try"对象的引用保存到CPU的寄存器中,该语句的跳转指令被屏蔽。然后执行finally中的return语句,该语句会将“finally”对象的引用保存到CPU的寄存器中(覆盖了try的),然后执行跳转指令。所以返回的是指向"finally"的指针,但是try中的return的确执行了。
package com.and.java.demo;
public class 测试 {
public static void main(String[] args) {
System.out.println(new 测试().test());
}
public String test() {
String result = "";
try {
result = "try";
return result;
} catch (Exception e) {
result = "catch";
return result;
} finally {
result = "finally";
}
}
}
分析以上代码,先执行try中的return语句(try中的语句总是先执行),该语句会将"try"对象的引用保存到CPU的寄存器中,然后执行finllay语句,该语句会将result局部变量的值重新定位成指向"finally"对象。最后执行跳转指令,因为CPU寄存器中保存的是“try”的引用,所以返回值是"try"的引用。
package com.and.java.demo;
public class 测试 {
public static void main(String[] args) {
System.out.println(new 测试().test());
}
public String test() {
try {
System.out.println("try{...}");
return "try";
} catch (Exception e) {
System.out.println("catch{...}");
return "catch";
} finally {
System.out.println("finally{...}");
return "finally";
}
}
}
分析以上代码,先执行try中的return语句,该语句会将"try"对象的引用保存到CPU的寄存器中,该语句的跳转指令被屏蔽。然后执行finally中的return语句,该语句会将“finally”对象的引用保存到CPU的寄存器中(覆盖了try的),然后执行跳转指令。所以返回的是指向"finally"的指针,但是try中的return的确执行了。
package com.and.java.demo;
public class 测试 {
public static void main(String[] args) {
System.out.println(new 测试().test());
}
public String test() {
String result = "";
try {
result = "try";
return result;
} catch (Exception e) {
result = "catch";
return result;
} finally {
result = "finally";
}
}
}
分析以上代码,先执行try中的return语句(try中的语句总是先执行),该语句会将"try"对象的引用保存到CPU的寄存器中,然后执行finllay语句,该语句会将result局部变量的值重新定位成指向"finally"对象。最后执行跳转指令,因为CPU寄存器中保存的是“try”的引用,所以返回值是"try"的引用。
关闭
我只是坚持我的兴趣。
有所专而多能,精于一而博学。
-
个人资料
- 访问:620521次
- 积分:4873
- 等级:
- 排名:第5919名
- 原创:39篇
- 转载:108篇
- 译文:4篇
- 评论:103条
-
友情链接
-
文章搜索
-
文章分类
- Android(45)
- Android 数据存储(2)
- Android 自定义UI控件(6)
- Android 进程与线程(2)
- Android 多媒体(3)
- Android 编程规范(2)
- PHP(1)
- Java(19)
- Web 开发(4)
- 随笔(3)
- 创业(1)
- 软件安装及配置(9)
- 有启发的时文(5)
- 算法(9)
- 计算机网络(9)
- Epub(3)
- 其他(6)
- 操作系统(3)
- 编译原理(1)
- UML(1)
- 笔试面试题(6)
- C#开发(3)
- JavaScrip & Node.js(5)
- Git(1)
-
阅读排行
- (133862)
- (57078)
- (25782)
- (18333)
- (17579)
- (16685)
- (15445)
- (15132)
- (14486)
- (13713)
-
评论排行
- (30)
- (28)
- (6)
- (5)
- (4)
- (3)
- (2)
- (2)
- (2)
- (2)
-
推荐文章
-
最新评论
-
: @mochounv:会执行的,建议你去实践一下。
-
: 666
-
: 厉害了
-
: 感觉大公司的笔试面试就是另一种方式的计算机考研。
-
: @aliangshuang:谢谢层主!
-
: 如果finally中没有return语句,但是改变了要返回的值,这里有点类似与引用传递和值传递的区别...
-
: @pairsfish:date类型底层貌似是对long类型的数据的封装,也就是说JVM可能在编译的时...
-
: @VirgoSoy:我觉得你总结的很好,很有道理。Java关于方法返回值应该就是对这个引用(或者基本...
-
: catch 中有throw 的话,finally不会执行
-
: 针对第一点,如果catch块中有System.exit(0);那么finally块是不会执行的。tr...
关闭
我只是坚持我的兴趣。
有所专而多能,精于一而博学。
-
个人资料
- 访问:620521次
- 积分:4873
- 等级:
- 排名:第5919名
- 原创:39篇
- 转载:108篇
- 译文:4篇
- 评论:103条
-
友情链接
-
文章搜索
-
文章分类
- Android(45)
- Android 数据存储(2)
- Android 自定义UI控件(6)
- Android 进程与线程(2)
- Android 多媒体(3)
- Android 编程规范(2)
- PHP(1)
- Java(19)
- Web 开发(4)
- 随笔(3)
- 创业(1)
- 软件安装及配置(9)
- 有启发的时文(5)
- 算法(9)
- 计算机网络(9)
- Epub(3)
- 其他(6)
- 操作系统(3)
- 编译原理(1)
- UML(1)
- 笔试面试题(6)
- C#开发(3)
- JavaScrip & Node.js(5)
- Git(1)
-
阅读排行
- (133862)
- (57078)
- (25782)
- (18333)
- (17579)
- (16685)
- (15445)
- (15132)
- (14486)
- (13713)
-
评论排行
- (30)
- (28)
- (6)
- (5)
- (4)
- (3)
- (2)
- (2)
- (2)
- (2)
-
推荐文章
-
最新评论
-
: @mochounv:会执行的,建议你去实践一下。
-
: 666
-
: 厉害了
-
: 感觉大公司的笔试面试就是另一种方式的计算机考研。
-
: @aliangshuang:谢谢层主!
-
: 如果finally中没有return语句,但是改变了要返回的值,这里有点类似与引用传递和值传递的区别...
-
: @pairsfish:date类型底层貌似是对long类型的数据的封装,也就是说JVM可能在编译的时...
-
: @VirgoSoy:我觉得你总结的很好,很有道理。Java关于方法返回值应该就是对这个引用(或者基本...
-
: catch 中有throw 的话,finally不会执行
-
: 针对第一点,如果catch块中有System.exit(0);那么finally块是不会执行的。tr...
这是我的理解,或许存在误解欢迎指点。。。(*^__^*) 嘻嘻