try-catch-finally
是一种针对程序运行时出错的响应手段,对于一些可以预料到的出错类型,在发生时对其进行报告和补救。其使用流程如下:首先执行try
中的语句,如果try
中的语句报错了,那么就转入对应的catch
语句中执行处理异常的措施,catch
后的语句中的内容是对应的错误类型。无论异常是否发生,finally
中的内容一定是会被执行的,一般用来释放资源,并确保某些操作一定会执行。当try和catch中有return时,finally中代码仍然会执行。
其使用的格式如下:
try {
} catch (IOException e) {
} finally { // 关闭资源
res.close();
}
public class TestTryFinally {
public static void main(String[] args) {
System.out.println(test01());
}
private static int test01() {
int num = 0;
try {
System.out.println("try block");
num = 10;
return num;
} catch (Exception e) {
System.out.println("catch block");
} finally {
System.out.println("finally block");
num = 30;
}
return num;
}
}
输出结果:
try block
finally block
10
说明return
语句已经执行了再去执行finally
语句,不过并没有直接返回,而是等finally
语句执行完了再返回结果。
public class TestTryFinally {
public static void main(String[] args) {
System.out.println(test02());
}
private static String test02() {
try {
System.out.println("try block");
return test03();
} catch (Exception e) {
System.out.println("catch block");
} finally {
System.out.println("finally block");
}
return "";
}
private static String test03() {
System.out.println("invoke method: test03()");
return "method test03() return";
}
}
输出结果:
try block
invoke method: test03()
finally block
method test03() return
说明try
中的return
语句先执行了但并没有立即返回,等到finally
执行结束后再返回。
public class TestTryFinally {
public static void main(String[] args) {
System.out.println(test04());
}
/*
* finally块中的return语句会覆盖try块中的return返回
*/
private static String test04() {
String s = "init";
try {
System.out.println("try block");
return "try";
} catch (Exception e) {
System.out.println("catch block");
} finally {
System.out.println("finally block");
return "finally";
}
// return s;
}
}
输出结果:
try block
finally block
finally
这说明finally
里的return
直接返回了,就不管try
中是否还有返回语句,这里还有个小细节需要注意,finally
里加上return
过后,finally
外面的return s
就变成不可到达语句了,也就是永远不能被执行到,所以需要注释掉否则编译器报错。
import java.util.*;
public class TestTryFinally {
public static void main(String[] args) {
System.out.println(test01());
System.out.println("######################");
System.out.println(getMap().get("key").toString());
}
private static int test01() {
int num = 0;
try {
System.out.println("try block");
num = 10;
return num;
} catch (Exception e) {
System.out.println("catch block");
} finally {
System.out.println("finally block");
num = 30;
}
return num;
}
public static Map<String, String> getMap() {
Map<String, String> map = new HashMap<String, String>();
map.put("KEY", "INIT");
try {
map.put("KEY", "TRY");
return map;
} catch (Exception e) {
map.put("KEY", "CATCH");
} finally {
map.put("KEY", "FINALLY");
map = null;
}
return map;
}
}
我们先来看一下AI(ChatGPT3.5,Bard和文心一言3.5)给出的答案是什么。我们可以看到ChatGPT
和文心一言
给出的结果是:程序会抛出NullPointerException
异常,而Bard
给出的结果为:TRY
。
而实际运行代码,我们得到的结果为:FINALLY
。
输出结果:
try block
finally block
10
######################
try block
finally block
finally
为什么test01()
中finally
里的num = 30;
并没有起到作用,而getMap()
中finally
的map.put("key", "finally");
起了作用,而map = null;
却没起作用呢?这就是Java到底是传值还是传址的问题了,简单来说就是:Java中只有传值没有传址,这也是为什么map = null
这句不起作用。
public static void main(String[] args) {
System.out.println(test06());
}
private static int test05() {
int num = 10;
try {
System.out.println("try block");
num = 5 / 0;
return num;
} catch (Exception e) {
System.out.println("catch block");
num += 20;
} finally {
System.out.println("finally block");
num += 30;
}
return num;
}
输出结果:
try block
catch block
finally block
60
try
语句块中发生了除0异常,所以try
中的return
不会被执行到,而是接着执行捕获异常的catch
语句和最终的finally
语句,此时两者对num
的修改都影响了最终的返回值。
public static void main(String[] args) {
System.out.println(test06());
}
private static int test06() {
int num = 10;
try {
System.out.println("try block");
num = 5 / 0;
return num;
} catch (Exception e) {
System.out.println("catch block");
num += 20;
return num;
} finally {
System.out.println("finally block");
num += 30;
}
// return num;
}
输出结果:
try block
catch block
finally block
30
说明了发生异常后,catch
中的return
语句先执行,确定了返回值后再去执行finally
块,执行完了catch
再返回,finally
里对num
的改变对返回值无影响,原因同前面一样,也就是说情况与try
中的return
语句执行完全一样。