try finally 与 return 的微妙关系

众所周知,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 的话,会覆盖掉之前返回的结果。

扫描二维码关注公众号,回复: 9213299 查看本文章

第二种:

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 中做出的修改,最终结果会进行修改,如果是普通数据类型,就不会发生变化。

发布了39 篇原创文章 · 获赞 20 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/cong____cong/article/details/102323813