锁定老帖子 主题:finally 和 return
精华帖 (0) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-08-27
最后修改:2009-08-27
第一个: public static int test() { int j = 0; try { j = 1; System.out.println("try:" + j); return j; }catch (Exception e) { // TODO: handle exception }finally { j = 2; System.out.println("finally:" + j); } return j; } 第二个: public static Person testPerson(Person p) { try { p.name = "try"; return p; }catch (Exception e) { // TODO: handle exception }finally { p.name = "finally"; } p.name = "last"; return p; } class Person { String name; Person(String name) { this.name = name; } } 想想答案,运行后核对。你做对了玛? 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-08-31
|
|
返回顶楼 | |
发表时间:2009-08-31
|
|
返回顶楼 | |
发表时间:2009-08-31
最后修改:2009-08-31
这里要理解的是return操作是一个压栈的操作(这里是方法的调用,就是把一个方法的栈顶值拷贝到调用方法的栈顶。注:每个方法都有自己的栈)
这里还要区分的一点是 值类型 和引用类型 另一点要理解的就是finally这个关键字的特性,主要就是它是作为单独的例程来运行的,同时要注意它指令执行的不对称性就可以了。 对于值类型,java虚拟机调用jsr指令,在执行finally一开始 就拷贝一个副本到另外一个地址(不是一开始j使用的地址),在finally正常执行结束后,调用ret指令把该值拷回栈顶。所以在finally中在对j进行操作是改变不了j的值的。 而如果是引用类型,由于拷贝的都是地址,因此对于对象的改变,这些地址肯定还是指向改变后的对象的(同一个对象) 令:第二个例子中 try中有了return了,下面在改变也没有用了,不会执行 深入JVM中专门有一章讲解了finally |
|
返回顶楼 | |
发表时间:2009-08-31
jiyanliang 写道 这里要理解的是return操作是一个压栈的操作(这里是方法的调用,就是把一个方法的栈顶值拷贝到调用方法的栈顶。注:每个方法都有自己的栈)
这里还要区分的一点是 值类型 和引用类型 另一点要理解的就是finally这个关键字的特性,主要就是它是作为单独的例程来运行的,同时要注意它指令执行的不对称性就可以了。 对于值类型,java虚拟机调用jsr指令,在执行finally一开始 就拷贝一个副本到另外一个地址(不是一开始j使用的地址),在finally正常执行结束后,调用ret指令把该值拷回栈顶。所以在finally中在对j进行操作是改变不了j的值的。 而如果是引用类型,由于拷贝的都是地址,因此对于对象的改变,这些地址肯定还是指向改变后的对象的(同一个对象) 令:第二个例子中 try中有了return了,下面在改变也没有用了,不会执行 深入JVM中专门有一章讲解了finally 那本书我是我计划中要看的书,但一直没找到合适的时间。 最近在找工作,郁闷的够呛 - - |
|
返回顶楼 | |
发表时间:2009-08-31
最后修改:2009-08-31
jiyanliang 写道 令:第二个例子中 try中有了return了,下面在改变也没有用了,不会执行 会执行 ps: 第一个例子返回的结果是1,但是finally里面有return j的话会得到 返回结果为2 第二个例子中name返回值结果应该是finally |
|
返回顶楼 | |
发表时间:2009-08-31
最后修改:2009-08-31
iaimstar 写道 jiyanliang 写道 令:第二个例子中 try中有了return了,下面在改变也没有用了,不会执行 会执行 ps: 第一个例子返回的结果是1,但是finally里面有return j的话会得到 返回结果为2 第二个例子中name返回值结果应该是finally 不好意思 我没有说明白。finally是不管怎么样都要执行的,我说的是 p.name = "last"; return p; 这句,他没有执行 |
|
返回顶楼 | |
发表时间:2009-08-31
jiyanliang 写道 这里要理解的是return操作是一个压栈的操作(这里是方法的调用,就是把一个方法的栈顶值拷贝到调用方法的栈顶。注:每个方法都有自己的栈)
这里还要区分的一点是 值类型 和引用类型 另一点要理解的就是finally这个关键字的特性,主要就是它是作为单独的例程来运行的,同时要注意它指令执行的不对称性就可以了。 对于值类型,java虚拟机调用jsr指令,在执行finally一开始 就拷贝一个副本到另外一个地址(不是一开始j使用的地址),在finally正常执行结束后,调用ret指令把该值拷回栈顶。所以在finally中在对j进行操作是改变不了j的值的。 而如果是引用类型,由于拷贝的都是地址,因此对于对象的改变,这些地址肯定还是指向改变后的对象的(同一个对象) 令:第二个例子中 try中有了return了,下面在改变也没有用了,不会执行 深入JVM中专门有一章讲解了finally 《Inside the Java Virtual Machine》的第二版已经很老了……从现状来看它已经老到足以误导人。 看这里, 引用 Bug 4381996 fixed: javac no longer generates the jsr instruction, instead inlining the finally clause.
于是Sun的javac从1.4.2开始就已经不生成JSR指令了。不然大家可以试试拿楼主的代码编译后javap看看。 hmm……大家继续讨论~ |
|
返回顶楼 | |
发表时间:2009-08-31
最后修改:2009-08-31
恩 确实如楼上所说。
之前看过inline方面的资料,竟然没有引起偶的重视。 |
|
返回顶楼 | |
发表时间:2009-09-01
第二个可以理解,第一个不太懂。
为什么我debug的时候两次到达try语句中的return j; 这句话上面,而且j的值也改变了(第一次是1,第二次是2),最后居然还是返回了1。不懂。 而且jiyanliang说"这里要理解的是return操作是一个压栈的操作(这里是方法的调用,就是把一个方法的栈顶值拷贝到调用方法的栈顶。注:每个方法都有自己的栈)"。但是这个try/catch不是在同一个方法里面吗,怎么说每个方法都有自己的栈呢? |
|
返回顶楼 | |