Java学习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里面的操作的,但是为什么不会输出的结果不会变呢。

查阅了相关的博客
明白了执行的顺序,在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喽。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值