try finally 与 return 的微妙关系

本文探讨了Java中try-catch-finally语句块与return语句的交互,说明finally块通常总会在return之前执行。通过示例展示了在finally块内改变返回值的情况,解释了当返回值是基本类型时,返回值不会被finally块修改,而如果是对象引用,则finally块的修改会影响最终结果。最后总结了finally块对不同类型的返回值的影响差异。
摘要由CSDN通过智能技术生成

众所周知,Java中异常处理机制try-catch-finally,try用来捕获异常,然后交给catch语句进行处理,finally用来替补,无论try中与catch中的遇到什么问题,fincally语句中都会被执行。

但是先给大家一个开胃菜:

public class ReturnFinally {
	public static void main(String[] args) {
		System.out.println(test1());
	}

	public static int test1() {
		int b = 20;
		try {
			System.out.println("try");
			return b += 80; 
		}
		catch (Exception e) {
			System.out.println("catch");
		}
		finally {
			System.out.println("finally");
			System.out.println("b = " + b);
		}
		return b;
	}
}

猜猜它的运行结果。

try
finally
b = 100
100

结果如上。return 语句的主要作用是结束当前方法,同时看看有没有需要带一个参数返回一下。既然是结束当前方法,那么上面就不应该输出finally和b=100?这个足以证明,finally大部分情况都会被执行,既然是大部分,那么特例是?System.exit(0);,因为这个句话是结束JVM,既然运行环境虚拟机都关闭了,那么肯定不会走了。

再给大家来个例子,擦亮眼睛,仔细斟酌

public class ReturnFinally {
	public static void main(String[] args) {
		System.out.println(test11());
	}

	public static String test11() {
		try {
			System.out.println("try");
			return test12();
		} finally {
			System.out.println("finally");
		}
	}
	public static String test12() {
		System.out.println("test12");

		return "after return";
	}
}

运行结果

try
test12
finally
after return

通过结果分析可以看出来,finally 都是在 return 之前运行的,那么有人该想了,如果在 finally 改变一下返回结果的值的值,那么最终的值会不会发生改变?

public class ReturnFinally {
	public static void main(String[] args) {
		System.out.println(test11());
	}

	public static int test11() {
		int n=0;
		try {
			System.out.println("try");
			n+=10;
			return n;
		} finally {
			System.out.println("finally");
			n+=20;
			System.out.println("n="+n);
		}
	}
}

运行结果

try
finally
n=30
10

运行的顺序和之前都一样,但是结果可能出乎大家的意料。我来给大家分析一下:运行到 n+=10;的时候,n 的值为10,然年执行 return n;此时的 n 并没有发生改变,然后程序会走到 finally 语句块中,执行 n+=20; n 的值发生改变,在原来的基础之上加20,所以输出的结果是 n=30,但是要注意,Java 方法返回数据,都是以值的方式返回的,也就是在返回的时候 n 是多少就是多少,不会改变了。有两种种情况会覆盖返回的结果

public class ReturnFinally {
	public static void main(String[] args) {
		System.out.println(test11());
	}

	public static String test11() {
		String s = new String();
		try {
			System.out.println("try");
			s+="try";
			return s;
		} finally {
			System.out.println("finally");
			s+="finally";
			System.out.println("s="+s);
			return s;
		}
	}
}

运行结果

try
finally
s=tryfinally
tryfinally

从这例子中可以看出,在 finally 写上一个 return 的话,会覆盖掉之前返回的结果。

第二种:

public class ReturnFinally {
	public static void main(String[] args) {
		System.out.println(test11());
	}

	public static List test11() {
		List s = new ArrayList();
		try {
			System.out.println("try");
			s.add("try");
			return s;
		} finally {
			System.out.println("finally");
			s.add("finally");
			System.out.println("s="+s);
			return s;
		}
	}
}

运行结果

try
finally
s=[try, finally]
[try, finally]

看到结果有人就纳闷了,同样的写法,return n 的时候 n 也没有发生变化,但是这里的 List 怎么变了。这个涉及到一个知识点,就是传值还是传地址的问题。有兴趣大家可以查阅一下资料,简单的说就是上面的那个例子 return n 的时候实际上是有一个新的 n 进行返回了,返回的是 n 的值,不是它的地址;但是 List 这个例子,在 new ArrayList 的时候在堆内存中声明一块空间,return 返回的是 List 所对应的地址,所以在 finally 中进行修改,它会跟着变化。


总结

Java 中 finally 无论 try 与 catch 中遇到任何问题,finally 语句中的内容都会被执行,如果返回的值是对象,那么 finally 中做出的修改,最终结果会进行修改,如果是普通数据类型,就不会发生变化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值