try_catch_finally关键字相关问题

Posted by Chenyawei on 2019-12-08
Words 1.1k and Reading Time 4 Minutes
Viewed Times

1. 什么时候用到finally呢? finally关键词在异常处理中如何使用:

不管异常会不会被捕捉或者处理都会执行的代码,某些事物(除内存外)在异常处理完后需要恢复到初始状态,如关闭IO操作, 关闭一些耗性能的资源,数据库的连接。

某些事物(除内存外)在异常在异常处理完后需要恢复到初始状态,如开启的文件,网络的连接等。

2. try里有return,finally还执行么?inally语句在try或catch中的return语句执行之后,还是return返回之前执行呢?

这个题目也是考查异常相关的。对于这个题目,我们通过代码来验证我们的答案,因为有异议的知识点,代码是最有说服力的。这个问题是一个很经典的问题,经常被面试官问,如果自己不去实验一下,可能判断就会出错。我们结合代码来分析一下。下面我们通过4个demo来得出最终结论。

  • test1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package hello;

public class Test01 {
public static void main(String[] args) {
System.out.println("test1():" + test1());
}
private static int test1() {
int i = 1;
try {
System.out.println("try...");
return i += 10;
} catch (Exception e) {
System.out.println("catch...");
} finally {
i++;
System.out.println("finally...");
System.out.println("i=" + i);
}
return i;
}

}

执行结果:
try...
finally...
i=12
test1():11

总结:finally代码块是在try代码块中的return语句执行之后,返回之前执行的。最外面的return i; 没有执行。无论finally代码块执行什么,返回值不变。

  • test2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class TestMain {
public static void main(String[] args) {
test2();
}
private static int test2() {
int i = 1;
try {
System.out.println("try...");
return i += 10;
} catch (Exception e) {
System.out.println("catch...");
} finally {
i++;
System.out.println("finally...");
System.out.println("i=" + i);
return i;
}
}
}

执行结果:
try...
finally...
i=12

总结:finally代码块中的return语句覆盖try代码块中的return语句。

  • test3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.util.HashMap;
import java.util.Map;
public class TestMain {
public static void main(String[] args) {
Map<String, String> map = test3();
System.out.println(map.get("KEY"));
}
private static Map<String, String> test3() {
Map<String, String> map = new HashMap<String, String>();
map.put("KEY", "INIT");
try {
System.out.println("try...");
map.put("KEY", "TRY");
return map;
} catch (Exception e) {
System.out.println("catch...");
map.put("KEY", "CATCH");
} finally {
System.out.println("finally...");
map.put("KEY", "FINALLY");
map = null;
}
return map;
}
}
执行结果:
try...
finally...
FINALLY

总结: 如果finally语句中没有return语句覆盖返回值,那么原来的返回值可能因为finally里的修改而改变也可能不变。传值类型的返回值:不变;传址类型的返回值:会变。

这里引入来一个新的问题,怎么判断一个变量是传值还是传址?

传值:8种基本数据类型及其包装类,字符常量。不变

传址:数组和对象。会变

  • test4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class TestMain {
public static void main(String[] args) {
System.out.println("test4返回:" + test4());
}
private static int test4() {
int i = 1;
try {
System.out.println("try...");
i = i / 0;
return i += 10;
} catch (Exception e) {
System.out.println("catch...");
return i;
} finally {
i++;
System.out.println("finally...");
System.out.println("i=" + i);
}
}
}
执行结果:
try...
catch...
finally...
i=2
test4返回:1

总结: try代码块中的return语句在异常的情况下不会被执行,这样具体返回哪个看情况;catch中的return执行情况与未发生异常时try中return的执行情况完全一样(如test4最后返回还是1)。

3. 如果执行finally代码块之前方法返回了结果,或者JVM退出了,finally块中的代码还会执行吗? 在什么情况下,finally语句不会执行

  1. try语句没有被执行,如在try语句之前就返回了,这样finally语句就不会执行;因此说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到。
  2. 如果在try代码块中执行System.exit(0)语句;那么将终止Java虚拟机JVM,因此,finally语句也不会被执行到。
  3. finally块的语句在try或catch中的return语句执行之后返回之前执行且finally里的修改语句可能影响也可能不影响try或catch中return已经确定的返回值,如果返回值类型为传址类型,则影响;传值类型,则不影响。
  4. 若finally里也有return语句则覆盖try或catch中的return语句直接返回。

notice

欢迎访问 chenyawei 的博客, 若有问题或者有好的建议欢迎留言,笔者看到之后会及时回复。 评论点赞需要github账号登录,如果没有账号的话请点击 github 注册, 谢谢 !

If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !