【转】Java中finally的执行时机

原文链接 http://blog.csdn.net/imzoer/article/details/8037970

finally是在catch执行之后return之前执行的。

那么,如果在finally中改变了catch中要返回的对象,那么,返回值改变了吗?

看代码:

上面代码输出是3,说明finally中的改变对catch中的返回值产生了影响。

再看下面代码:

奇怪的是,上面的代码输出的竟然是2。 原因还是稍微深奥的。

解释下: 这里面,涉及到一个栈帧的问题。 在catch中执行的时候,return之前是需要去执行finally的。

执行finally之前,把当前要返回的值的引用保存到一个slot【槽】中,也就是说return已经执行,

但是还没返回(在MyEclipse的debug模式下可以看的很清楚),把当前要返回的值保存起来了。

然后执行finally,执行完finally,再从slot中取出要返回的值进行返回。

如果返回的是一个对象的引用的话,那么将是finally执行后的值。如果是一个基本类型的话,

那么返回的就只是那个基本类型的值了。 【在这里需要注意一点的是,当返回值是对象,

而不是普通的java基本类型的时候,在finally中的修改会反映到返回值中(第一个例子),

但是如果是普通的java基本类型,那么finally中的修改就不会反映到返回值中了,

表现出来就是,finally虽然修改了,但是返回值仍然是2,见上面的代码(第二个例子)】。

修改会反映到返回值中,是因为存储在slot中的是对象的引用。

在finally中修改的时候,修改的内容已经保存到堆中的对象了。

此时return,会反映出修改后的结果。

时间: 2024-10-06 11:40:21

【转】Java中finally的执行时机的相关文章

Java中线程顺序执行

现有线程threadone.threadtwo和threadthree,想要的运行顺序为threadone->threadtwo->threadthree,应该如何处理?这里需要用到一个简单的线程方法join(). join()方法的说明:join方法挂起当前调用线程,直到被调用线程完成后在继续执行(join() method suspends the execution of the calling thread until the object called finishes its ex

Java中停止线程执行的方法

Java中停止线程执行的方法 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs 一.暂停或停止线程的理论 在Java编程中,要暂停或停止当前正在运行的线程,有几种方法.对于把线程转入睡眠Sleep状态,使用Thread.sleep()是最正确的方式.或许有人会问,为什么不使用等待wait()或通知notify()?要知道,使用等待或通知都不是很好的方式. 线程可以使用等待wait()实现被阻塞,这属于条件等待的方式,当条件满足后,又会从阻塞转为等待状态

java的static块执行时机

一.误区:简单认为JAVA静态代码块在类被加载时就会自动执行.证错如下: [java] view plain copy class MyClass1 { static {//静态块 System.out.println("static block "); } } public class Main { Class[] classArray = { MyClass1.class//这样引用该类,必然需要将该类加载到虚拟机中 }; public static void main(Strin

Java中代码块执行顺序

代码块:在Java中,使用{}括起来的代码被称为代码块.根据其位置和声明的不同,可以分为 局部代码块:局部位置,用于限定变量的生命周期.构造代码块:在类中的成员位置,用{}括起来的代码.每次调用构造方法执行前,都会先执行构造代码块.作用:可以把多个构造方法中的共同代码放到一起,对对象进行初始化.静态代码块:在类中的成员位置,用{}括起来的代码,只不过它用static修饰了.作用:一般是对类进行初始化. 静态代码块,构造代码块,构造方法的执行顺序? 首先执行静态代码块 接着执行构造代码块 最后指向

java中程序的执行的原理如怎么创建空间,创建对象等

这里举一个简单的例子: public class Test{ public static void main(String[] args){ String s; s = "hello world"; Student s1 ; s1 = new Student();//这里Student是引用类型 System.out.println(s); } } 就这个简单的程序我来说一下其工作的原理,希望能有助于跟我一样的菜鸟: 编译器通过主类找到编译入口编译成class文件,通过加载类到内存中(

深入理解java中HelloWorld的执行流程

HelloWorld.java是我们学习java的第一个程序,简单的再也不能简单了,可是里面的原理以及执行流程大家都知道吗?最近在复习java知识,特地钻研了一番分享给大家! 贴出HelloWorld的代码如下: public class HelloWorld { public static void main(String[] args) { String s ; s = “Hello World!”; //定义字符串s System.out.println(s); } } 分析内存图: He

关于Java中一个Class执行先后次序的问题

首先贴出代码,如下: public class Test { public static void main(String[] args) { A a=new B(); a.a(); }} class A{ public A(){ System.out.println("I'am A"); } static{ System.out.println("AAAAA"); } { System.out.println("111"); } public

java中的一些执行顺序,代码块,静态,构造,成员。。。。(转的)

Java初始化顺序(转来的) 1在new B一个实例时首先要进行类的装载.(类只有在使用New调用创建的时候才会被java类装载器装入) 2,在装载类时,先装载父类A,再装载子类B3,装载父类A后,完成静态动作(包括静态代码和变量,它们的级别是相同的,安装代码中出现的顺序初始化)4,装载子类B后,完成静态动作类装载完成,开始进行实例化1,在实例化子类B时,先要实例化父类A2,实例化父类A时,先成员实例化(非静态代码)3,父类A的构造方法4,子类B的成员实例化(非静态代码)5,子类B的构造方法 先

java中for循环执行过程

for (int j = 0; j < newSize; j++) { //执行todo } 1.首先变量j初始化为0 2.然后j=0的值跟newSize进行比较,假如为true,则执行{}里面的内容,假如为false,则跳出循环体 3.{}执行完成,再执行j++ 4.j++执行完成,再跟newSize进行比较,假如为true,则执行{}里面的内容,假如为false,则跳出循环体 5.循环执行3和4