你真的了解try、catch、finally吗

使用Java进行开发的小伙伴,在工作中一定少不了接触 try/catch/finally,但是你真的掌握了这一块的知识点吗?

最近在看代码的时候,发现 Android 源码中 try / catch 的用法和我们平时用的不一样,大量地用到了 try / finally,而省略了 catch 的步骤。

通常,标准做法都是在 try 的代码块中执行主要逻辑,在 catch 的代码块捕获异常,在 finally 的代码块中执行资源关闭回收等操作。

用代码表示如下:

	private void testTryCatch() {
		try {
			// 执行主要逻辑,由于可能抛出异常,所以需要try/catch捕获异常
		} catch (Exception e) {
			// 捕获异常,防止程序崩溃
		} finally {
			// 做一些收尾工作
		}
	}

看起来它的用法似乎很简单,但是把这些简单的用法进行变换,你还能快速地读懂代码吗?

做一个测试,以下的三个函数,执行之后分别会有什么结果?

	private static void test1() {
		try {
			int a = 10;
			int b = 0;
			System.out.println("" + (a / b));
		} finally {
			System.out.println("finally");
		}
		System.out.println("it is ok");
	}

	private static int test2() {
		try {
			int a = 10;
			int b = 0;
			return (a / b);
		} finally {
			System.out.println("finally");
			return 1000;
		}
	}

	private static int test3() {
		try {
			int a = 10;
			int b = 0;
			return (a / b);
		} catch (Exception e) {
			System.out.println("Exception");
			throw new IOException();
		} finally {
			System.out.println("finally");
			return 1000;
		}
	}

关于 test1:

在执行 try 的代码时会抛异常,但是由于没有在 catch 中进行捕获,所以毫无疑问 test1 这个函数是会抛异常的。

问题就在于这里又实现了 finally 的代码块。我们都知道正常情况下 finally 的代码是肯定会执行的,那在抛出异常的情况下呢?

答案是 finally 仍会执行。先执行 finally 里面的代码,再将异常继续往上抛出。

test1 函数执行结果

关于 test2:

当函数是有返回值类型时,如果在 try 的代码块中出现异常,但又没捕获,那么外部调用的代码肯定无法正常获取返回值。

但是这里在 finally 中返回了一个值,所以函数不会继续往上抛异常,而是返回 finally 代码块中给定的返回值

test2 函数执行结果

关于 test3:

其实如果搞懂了 test2,那么 test3 也是同样的道理,虽然在 catch 代码块中抛出了异常,但是由于 finally 代码块中给定了返回值,所以上层能正常接收返回值,而不会发生异常。

test3 执行结果


总结如下:

1、无返回值函数,如果没有 catch 异常,finally 代码块会执行,再抛出异常

2、有返回值函数,如果在 finally 里面有返回值,[无论有没catch异常],都会正常返回,不抛异常

3、有返回值函数,如果在 finally 里面无返回值,且没有 catch 异常,则先执行 finally,再抛出异常

发布于 2020-07-23 13:57