3分钟告诉你try-catch-finally的return需要注意的问题

2023-05-06 20:24:18 浏览数 (1)

不用太多复杂的例子和解释,这里几个小例子大家就能懂。

eg1:

代码语言:javascript复制
public class Test {
	public static void main(String[] args) {
		System.out.println("开始");
		int num = 10;
		System.out.println(test(num));
	}

	public static int test(int b) {
		try {
			b  = 10; // 这里b变成了20
			return b  = 10; // 先执行return后面的表达式,b变成了30,表达式的值临时存储起来再去执行finally
		} catch (Exception e) {
			return 1;
		} finally {
			System.out.println("==="   b); // 30
			b  = 10; // 40
			return b; // 返回40
		}
	}
}

打印结果:

开始 ===30 40

注意点: try代码块中,return后面的表达式先执行再把值临时存储起来。接着执行finally代码块,执行完finally代码块后再去执行try代码块中的return。如果finally代码块中有return,那么就直接返回了,不会让try代码块中return返回。

eg2:(相比上一个例子区别仅为finally里没有return

代码语言:javascript复制
public class Test {
	public static void main(String[] args) {
		System.out.println("开始");
		int num = 10;
		System.out.println(test(num));
	}

	public static int test(int b) {
		try {
			b  = 10; // 这里b变成了20
			return b  = 10; // 先执行return后面的表达式,b变成了30,表达式的值临时存储起来再去执行finally
		} catch (Exception e) {
			return 1;
		} finally {
			System.out.println("==="   b); // 30
			b  = 10; // 40
		}
	}
}

运行结果:

开始 ===30 30

注意点: 即使finally代码块中b的值更改了,但是没有return返回,而try代码块中return的是上一次临时保存值30,所以最后返回打印30

需要注意的是,如果是引用类型,结果那就不一样了。

代码语言:javascript复制
public class Test {
	public static void main(String[] args) {
		System.out.println("开始");
		StringBuilder str = new StringBuilder("a");
		System.out.println(test(str));
	}

	public static StringBuilder test(StringBuilder s) {
		try {
			s.append("b"); // 这里s变成了"ab"
			return s.append("c"); // 先执行return后面的表达式,s变成了"abc",表达式的值临时存储起来再去执行finally,
			// 但是,这里临时保存的是引用!!在finally改变引用地址的值
		} catch (Exception e) {
			return null;
		} finally {
			System.out.println("==="   s); // "abc"
			s.append("d"); // s引用地址的值改为了"abcd"
		}
	}
}

运行结果:

开始 ===abc abcd

常用的需要记住的就这几个,如果有人问你catch里面再套几层try-catch-finally之类的。谁吃的这么饱啊,这个就和i i i i i ...一样无聊,不过finally最后都会一层层执行,推断和实验结果没有什么差异。

来看看你可能想知道的无聊的例子。

代码语言:javascript复制
public class Test {
	public static void main(String[] args) {
		System.out.println("开始");
		StringBuilder str = new StringBuilder("a");
		System.out.println(test(str));
	}

	public static StringBuilder test(StringBuilder s) {
		try {
			s.append("b"); 
			int bb = 1 / 0; // 制造运行时异常
			return s.append("c"); 
		} catch (Exception e) {
			try {
				throw new RuntimeException(" run error");
			} catch (Exception e1) {
				System.out.println("catch!!");
			} finally {
				int b = 1 / 0; // 制造运行时异常
//				System.exit(0);
				System.out.println("!!!");
			}
		} finally {
			System.out.println("==="   s); 
			s.append("d"); 
		}
		return null;
	}
}

运行结果:

记住finally不是一定执行,比如System.exit(0)后虚拟机退出,所有的finally都不执行,嵌套finally也没用,直接终止执行程序。

finally块中发生了异常而你没有捕捉,那么该finally块后面的代码就不会继续执行,如果外层还有finally,那么外层finally块是会执行的。

如果还有我没有讲到的,欢迎大家提问。

面试和笔试无非就是这些东西,难道还有更无聊的题?

0 人点赞