try-catch-finally 问题

yzb123 2009-08-24 11:24:48
大家看看以下代码:

public static String fun(){
String s = "abc";
try{
throw new Exception();
} catch (Exception e) {
return s;
} finally{
s = "s";
}
}

你们是怎么样理解的?
...全文
557 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhangshaohua01 2009-08-26
  • 打赏
  • 举报
回复
try里面放的是有可能出错的代码,
当执行到这里面时如果有异常则进入catch反之则不会执行catch,
而finally是不管有没有异常都会执行的代码块。
在catch已经返回s="abc"
之后才对s重新赋值
只有catch中有return
所以输出的是abc
翼海同行 2009-08-26
  • 打赏
  • 举报
回复
我只记得,try,catch,finally,大家都说finally最终都会执行,但是在多线程有一个方法是会绕过finally的,也就是finally会不执行。【大家可以去找下,我有点忘记了】
chenhao_283 2009-08-26
  • 打赏
  • 举报
回复
我站在旁边看看
hanger1212 2009-08-26
  • 打赏
  • 举报
回复
学习了
JavaHtmlCssJSP 2009-08-26
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 haojia0716 的回复:]
我不知道static和try catch finally有什么关系
[/Quote]
接受这个解释,如果finally中没有返回语句,不论在finally中做什么修改,都不会影响最后的返回结果。
haojia0716 2009-08-26
  • 打赏
  • 举报
回复
楼上所说的多线程的情况 指的是jvm运行的线程全是守护线程的情况下 会自动关闭jvm
守护线程一般是为非守护线程服务的 其他线程关闭了 守护线程也完成工作了 所以开着也没什么用 就关了
这种设计是很科学的

所以不是finally不会执行 而是jvm已经终止了 后面的任何程序段都不会执行
hotleavegjz 2009-08-26
  • 打赏
  • 举报
回复
下面的几个输入语句也许能更清楚的展现执行顺序:

public class Dummy2 {
public static void main(String[] args) {
String str = fun();
PrintUtil.print("return");
PrintUtil.print(str);
}



public static String fun(){
String s = "abc";
try{
throw new Exception();
} catch (Exception e) {
return fun2(s);
} finally{
s = "s";
PrintUtil.print("finally");
}
}

public static String fun2(String s){
PrintUtil.print("in fun2 s=" +s);
return s;
}
}


执行结果:
in fun2 s=abc
finally
return
abc

即: 在finally前执行了return语句, 但是并没有真正的返回, 而是去执行了finally,
然后再将结果返回.
于是做了一下更改:
1. 将fun2的返回值改为其他值, 则整个fun的返回值等于fun2的返回值
2. 在finally里添加return语句, 则整个fun的返回值等于finally里的返回值.
haojia0716 2009-08-25
  • 打赏
  • 举报
回复
我不知道static和try catch finally有什么关系
yqsshr 2009-08-25
  • 打赏
  • 举报
回复
3\4楼已经说清原由了吧
haojia0716 2009-08-25
  • 打赏
  • 举报
回复
请问 局部变量可以用static吗


而且 在这里 我就是故意改成成员变量来说明问题的
haojia0716 2009-08-25
  • 打赏
  • 举报
回复
最好不要在finally里写return
finally一般用作关闭资源 释放资源
dz007 2009-08-25
  • 打赏
  • 举报
回复
测试代码,在return后停了下来,执行finally后返回

static String s = "abc";

public static String fun() {
try {
throw new Exception();
} catch (Exception e) {
System.out.println("return");
return s;
} finally {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("finally");
s = "s";
}
}

public static void main(String[] args) throws Exception {
Test T1 = new Test();
System.out.println(T1.s);
System.out.println(T1.fun());
System.out.println(T1.s);
}


打印结果:
abc
return
(有停顿)
finally
abc
s
lovecj6185 2009-08-25
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 haojia0716 的回复:]
引用 14 楼 lovecj6185 的回复:
拜托楼上各位测试的时候别用
static String s;
特别是建议不要用static

用了static,变量的性质发生了很大的变化
无法说明楼主的问题吧


为什么不能说明

这里又不存在多线程安全性问题
[/Quote]


楼主代码里的
String s = "abc";
s 是个局部变量

如果你加了static的话
s就变成了全局的静态变量

static的用法不要我说了吧
在任何一处更改都会受影响

如果把这个变量加上static
那讨论try,catch,finally,有何意义?
更何况里面还有return
dz007 2009-08-25
  • 打赏
  • 举报
回复
我的理解,return之后不会立刻返回,但这时已指定了返回对象,执行完finally之后再返回
返回的值是对象"abc" ,s指向了新的值"s"
haojia0716 2009-08-25
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 wodwl 的回复:]
引用 3 楼 chenchengamao 的回复:
finally中对变量s的修改并不会改变s的原来返回值,s的值还是"abc"

请看下面的测试:证明s的值最终改变了
public class Tester {
static String s = "abc";

public static String fun() {
try {
throw new Exception();
} catch (Exception e) {
return s;
} finally {
s = "s";
}
}

public static void main(String[] args) {
String str = new Tester().fun();
System.out.println(str);
System.out.println(s);
}
}
运行结果:
abc
s

[/Quote]


反正finally最后是会被执行的

还有这种写法是不规范的
yzb123 2009-08-25
  • 打赏
  • 举报
回复

public Map returnMap() {
try {
x.put("8", "8");
return x;
} finally {
// x = new HashMap <String, String>();
x.put("7", "7");
}
}

public String fun(){
String s = "abc";
try{
throw new Exception();
} catch (Exception e) {
return s;
} finally{
s = "s";
}
}

public String fun2(){
try{
throw new Exception();
} catch (Exception e) {
return "123";
} finally{
return "abc";
}
}


我的解释是这样:
String 显然是对象,在catch里碰到了return,此时已经拷贝了String对象的地址到了程序返回的变量(如大伙所说的)
然后,程序进入了finally 语句块,此时 变量 s 指向了另外一个String对象"s"(原因String是被final修饰的)所以程序返回的变量的值仍然指向 "abc" 的地址。
对于map的解释:
因为HashMap是没被final 修饰,
所以程序返回的变量 与finally里修改的map的实例指向同一个地址。
所以返回的Map实例是包含了两个键值对.
对于catch和finally 都有return的情况,我的解释是:当程序跑到catch里的return时,则程序的返回变量的值 此时指向了 当前return的值,然后程序继续执行finally的return,此时程序的返回变量值会覆盖了先前的值,所以程序真正返回 又会是finally里return的值
haojia0716 2009-08-25
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 lovecj6185 的回复:]
拜托楼上各位测试的时候别用
static String s;
特别是建议不要用static

用了static,变量的性质发生了很大的变化
无法说明楼主的问题吧
[/Quote]

为什么不能说明

这里又不存在多线程安全性问题
lh_fengyuzhe 2009-08-25
  • 打赏
  • 举报
回复
学习
lovecj6185 2009-08-25
  • 打赏
  • 举报
回复
拜托楼上各位测试的时候别用
static String s;
特别是建议不要用static

用了static,变量的性质发生了很大的变化
无法说明楼主的问题吧
sunnyfun888 2009-08-25
  • 打赏
  • 举报
回复
这说明java是值传递,在到 return s; 时,将s的值拷贝了一份放到的函数的返回值
而finally总是会被执行,在跳出函数前,finally内的代码得到了执行的机会,从而使 s = "s";

另:就算返回类型是对象类型,还是值传递,只不过因为对象变量内放的是引用的地址,返回时是引用的地址的一份拷贝,而不是整个对象实例的拷贝(那变成克隆了)。

根据推荐的java规范,一个函数只能有一个retrun,那么显然retrun应该放在“踹开吃”外面,楼主的这种写法是不规范的。
加载更多回复(11)

62,615

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧