try finally return 奇怪现象

最近在逛博客的时候,发现了一个有趣的事情
当我面对如下的表达式的时候

public static int test(){
	int i = 1;
	try{
	return ++i;
	}finally{
		i = i+2;
	}
}

我在想,呀这个应该怎么执行呢。首先我们分析一下
有一个return 语句,那么按照java的规范,return语句中断当前的函数(方法),也就是说按道理直接返回2。那么finally是不是不会执行了吗。输出的结果也真的如同我们所想。于是我尝试了一下,加上了System.out.println(“see there”);

public static String testStr(){
	String str = "hello";
	try{
		return str;
	}finally{
		System.out.println("see there");
		str = str + " world";
	}
}

得到的控制台输出竟然有see there ,输出的结果依然是hello,那么证明一件事,当我们运行上面的程序的时候,是会进行finally里面的操作的,但是为什么不会输出的结果不会变呢。
我去查阅了相关的博客,http://www.cnblogs.com/averey/p/4379646.html#!comments
明白了执行的顺序,在java的规范里面
如果在try语句里有return语句,finally语句还是会执行。它会在把控制权转移到该方法的调用者或者构造器前执行finally语句。也就是说,使用return语句把控制权转移给其他的方法前会执行finally语句。
另外jvm规范里面
如果try语句里有return,那么代码的行为如下:
1.如果有返回值,就把返回值保存到局部变量中
2.执行jsr指令跳到finally语句里执行
3.执行完finally语句后,返回之前保存在局部变量表里的值

也就是说,jvm会在进行try操作中return 语句的时候,会执行return后面的相关语句,但是如果后面还有finally,那么try里面的return不会立刻返回,而是创建一个局部变量来进行保存当前值,你可以认为是开辟了一个新的基本类型变量,然后执行后面的finally里面的操作,但是不管怎么操作,因为基本数据类型,是值传递(放在栈里面),所以不会影响到局部变量
至于String类型,因为String类型是引用类型,也就是说,他会在栈里面存放一个内存地址,在方法区那边存放一个常量,那么我们不能修改方法区里面的常量,但是我们修改的是栈里面的内存地址,使得指向其他位置。所以不会对return的返回结果又影响。
那么说道现在,你因为也明白了,既然String类型,基本数据类型我们都尝试过了,那我来进行尝试一下其他类型的对象吧。结果你应该明白,对象的值会发生变换。解释一下:我们如果创建一个对象,那么我们会在栈里面创建一个地址,这个地址来存放我们需要放置的对象位置,对象位置存放于堆中,在堆中,我们又会存放指向实际变量的内存地址。也就是说,如果是对象,那么内存里面的情况是这样存放
------------》--------------》堆或方法区
所以如果是包装类,那么会发生变化。也就是说:

public static data testData(){
	data d = new data();
	try{
	return d;
	}finally{
	d.str = "hello world";
	}
}

private static class data(){
	private String str = "hello";
	@Override
	public String toString(){
		return str;
	}
}

那么结果会输出为hello world。

那么你可能会问,如果我在finally里面使用了return呢
那么他会运行完finally里面的内容后不会再跑上去执行try里面的return的代码。也就是说

public static int test(){
	int i = 1;
	try{
	return ++i;
	}finally{
	return ++i;
	}
}

将会输出3喽。
完美

猜你喜欢

转载自blog.csdn.net/qq_41967899/article/details/88684149
今日推荐