Java中,finally通常和try catch一同使用,表示无论程序正常运行,还是出现异常,finally块的内容一定会被执行。
return用来终止一个方法的执行,并返回值。
finally和return的执行顺序,也因为情况不同而有所不同。
1、try{} catch(){}finally{} return;
按照正常顺序执行
public class ReturnTest {
public static void main(String[] args){
int num = new ReturnTest().orderTest1();
System.out.println("最终返回结果为" + num);
}
public int orderTest1(){
int i = 0;
try{
int j = 1/2;
i = i + 1;
}catch (Exception e){
i = i + 2;
}finally {
i = i + 3;
}
i = i + 4;
return i;
}
}
2、try{ return; }catch(){} finally{} return;
当程序正常运行时,先执行try块,包括return表达式,然后执行finally块,然后将try块return返回;
当程序出现异常时,则按照正常顺序执行。
public class ReturnTest {
public static void main(String[] args){
System.out.println("正常运行最终返回结果为" + new ReturnTest().orderTest1());
System.out.println("出现异常最终返回结果为" + new ReturnTest().orderTest2());
}
public int orderTest1(){
int i = 0;
try{
int j = 1/2;
i = i + 1;
return i;
}catch (Exception e){
i = i + 2;
}finally {
i = i + 3;
}
i = i + 4;
return i;
}
public int orderTest2(){
int i = 0;
try{
int j = 1/0;
i = i + 1;
return i;
}catch (Exception e){
i = i + 2;
}finally {
i = i + 3;
}
i = i + 4;
return i;
}
}
从结果可以看出,由于try块中的return值已经确定了,所以虽然finally确实运行了,也确实改变了i的值,但已不会对return造成影响。
因此得出结论,finally中无return的时候,其对值做出的改变,不影响return值。
上面这段结论是否就一定正确呢?
我们知道Java分为值传递和引用传递。当对象为基本数据类型和字符串时,是值传递;当对象是引用数据类型时,则是引用传递。而我们上面的测试代码用的是int基本数据类型,如果我们换成一个引用对象,会有什么样的结果出现呢?
public class ReturnTest {
private String msg;
private int code;
public static void main(String[] args){
System.out.println("正常运行最终返回结果为" + new ReturnTest().orderTest1());
System.out.println("出现异常最终返回结果为" + new ReturnTest().orderTest2());
}
public ReturnTest orderTest1(){
ReturnTest returnTest = new ReturnTest();
try{
int j = 1/2;
returnTest.setCode(200);
returnTest.setMsg("正常");
return returnTest;
}catch (Exception e){
returnTest.setCode(404);
returnTest.setMsg("异常");
}finally {
returnTest.setCode(100);
returnTest.setMsg("finally中改变了值");
}
returnTest.setCode(0);
returnTest.setMsg("return");
return returnTest;
}
public ReturnTest orderTest2(){
ReturnTest returnTest = new ReturnTest();
try{
int j = 1/0;
returnTest.setCode(200);
returnTest.setMsg("正常");
return returnTest;
}catch (Exception e){
returnTest.setCode(404);
returnTest.setMsg("异常");
}finally {
returnTest.setCode(100);
returnTest.setMsg("finally中改变了值");
}
return returnTest;
}
}
可以发现,当为引用传递时,finally中的代码是会改变且影响return返回值的。
3、try{ } catch(){return;} finally{} return;
和上一种情况相反。正常运行时,按照既定顺序;当出现异常时,则是先catch块,包括catch中的return表达式,然后是finally块,最后弹栈返回值,方法执行结束。
同样的,当为值传递时,catch中的return值已经确定,finally不会对return产生影响。
引用传递时,finally会改变和影响return的值。
public class ReturnTest {
public static void main(String[] args){
System.out.println("正常运行最终返回结果为" + new ReturnTest().orderTest1());
System.out.println("出现异常最终返回结果为" + new ReturnTest().orderTest2());
}
public int orderTest1(){
int i = 0;
try{
int j = 1/2;
i = i + 1;
}catch (Exception e){
i = i + 2;
return i;
}finally {
i = i + 3;
}
i = i + 4;
return i;
}
public int orderTest2(){
int i = 0;
try{
int j = 1/0;
i = i + 1;
}catch (Exception e){
i = i + 2;
return i;
}finally {
i = i + 3;
}
i = i + 4;
return i;
}
}
4、try{ return; }catch(){} finally{return;}
程序先运行try块,包括return表达式;然后运行finally块,由于其中也有return,所以程序在finally中结束运行,弹栈返回值,而不会再去执行try中的return。
public class ReturnTest {
public static void main(String[] args){
System.out.println("正常运行最终返回结果为" + new ReturnTest().orderTest1());
}
public int orderTest1(){
int i = 0;
try{
int j = 1/2;
i = i + 1;
return i;
}catch (Exception e){
i = i + 2;
}finally {
i = i + 3;
return i;
}
}
}
5、try{} catch(){return;}finally{return;}
与4中的情况类似,程序在finally提前结束弹栈,不会执行catch中的return
public class ReturnTest {
public static void main(String[] args){
System.out.println("正常运行最终返回结果为" + new ReturnTest().orderTest1());
}
public int orderTest1(){
int i = 0;
try{
int j = 1/0;
i = i + 1;
}catch (Exception e){
i = i + 2;
return i;
}finally {
i = i + 3;
return i;
}
}
}
6、 try{ return;}catch(){return;} finally{return;}
情况4和5的结合
public class ReturnTest {
public static void main(String[] args){
System.out.println("正常运行最终返回结果为" + new ReturnTest().orderTest1());
System.out.println("出现异常最终返回结果为" + new ReturnTest().orderTest2());
}
public int orderTest1(){
int i = 0;
try{
int j = 1/2;
i = i + 1;
return i;
}catch (Exception e){
i = i + 2;
return i;
}finally {
i = i + 3;
return i;
}
}
public int orderTest2(){
int i = 0;
try{
int j = 1/0;
i = i + 1;
return i;
}catch (Exception e){
i = i + 2;
return i;
}finally {
i = i + 3;
return i;
}
}
}