try-catch,try-with-resource

try-catch和try-with-resource

第一部分 try-catch

  try-catch是为了处理异常而设计的机制,可以结合异常相关知识一起学习。

为什么要设计try-catch?

  程序需要有错误处理机制,所以有throws用来报错,也需要try-catch来处理错误。但try-catch需要被正确且合理的使用,需要每个开发人员搞懂原理和好的应用场景。

  如一些人会只抛出异常,全部throw,这种做法是在躲避异常,不是一种好的编程习惯,对于程序来说异常和错误总是需要解决的。但有一些人可能会在所有地方都try-catch,但并没有解决异常的能力没有真正的去处理异常,也就隐藏了BUG,同时也增加了try-catch的开发开销和性能开销,反而得不偿失。

项目中应该使用try-catch的场景有哪些?

  1. 当在业务模块遇到exception,一般会在底层throws,在业务顶层try-catch。比如登陆模块,我们实现了内部的登陆函数login(),那么就可能会有:UserNotFoundException、PwdNotMatchException等异常,如果在login()内try-catch,那么在表现层就无法详细的展示具体信息,当然总是会有解决办法的,比如返回errorcode,其相比直接throws让调用者处理来讲,至少首先灵活性差了,扩展性也不高,代码可复用性应该也比不上,这是我目前阶段的感受。

  2. 某些方法内需要进行一些处理,否则程序可能会崩溃或过度消耗资源,比如一些IO操作,网络操作。

  3. 需要对异常进行”翻译”、”记录”等情况,如隐藏一些数据库异常信息、记录异常日志。

  建议初学者先避免使用try-catch,抛出异常让有经验的来擦屁股,在掌握try-catch以及异常的相关知识,并对项目有一定的理解后再尝试使用,或者按照项目设计的异常处理机制来处理。

try-catch的优缺点?

优点:

  1. 增强了代码的鲁棒性。
  2. 比较灵活应对异常情况,提供解决方案。

缺点:

  1. 增加了代码的复杂度。
  2. 有一定的性能消耗。
  3. 在一定程度上会诱导初学者滥用。

结构和执行顺序

  try-catch-finally结构如下,可以看作不同的模块。正常流程下会走try块,当try块发生catch定义的Exception时就跳至catch块,而finally则一定会被执行。

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
try{
//code
}catch (ExceptionType1 ex1 | ExceptionType2 ex2){
//handler for this exception type
}finally {
//一定执行
}

//解耦合,实现单一职能,且可以捕获finally中异常
try{
//code
try{
//code
}finally {
//一定执行
}
}catch (ExceptionType1 ex1 | ExceptionType2 ex2){
//handler for this exception type
}

//也可以只有try-finally语句块
try{
//code
}finally {
}

  catch的异常可以合并,因为catch块只有发生异常时执行,而try内代码只有顺利的情况下才能全部执行,所以需要finally语句块可以保证某部分代码无论何种情况一定都会执行。比如读取文件流时,需要在退出方法前回收资源,最好的方法就是在finally语句块内执行,其执行顺序一直是最后且一定执行。

  finally中代码会在return之前执行,若finally中也有return语句会覆盖其它地方的return。如下代码测试,分别计算1,2,3输出结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[] args){
System.out.println("f(1): " +f(1));
System.out.println("f(2): " +f(2));
System.out.println("f(3): " +f(3));
}

public static int f(int n){
try{
int r = n * n;
return r;
}finally {
if(n == 2)
return 0;
}
}

  结果如下。

1
2
3
f(1): 1
f(2): 0
f(3): 9

  所以try-catch-finally执行顺序为:

1
2
3
4
5
6
7
1. run try-code
2. if has exception then goto 3 else 6
3. run catch-code
4. run finally-code
5. if finally-code has return then return-finally else return-catch
6. run finally-code
7. if finally-code has return then return-finally else return-try

第二部分 try-with-resource

  Java SE7 以后新增了带资源的try语句,当try块退出时会自动调用res.close。

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
try(Resource res = ...){
work with res
}

//try-catch-finally关闭文件资源
public static void main(String[] args){
try {
Scanner in = new Scanner(new FileInputStream("/in.txt"),"UTF-8");
PrintWriter out = new PrintWriter("/out.txt");
while (in.hasNext())
out.println(in.next().toUpperCase());
}catch (FileNotFoundException ex){
ex.printStackTrace();
}
}

//try-with-resource关闭文件资源
public static void main(String[] args){
try (Scanner in = new Scanner(new FileInputStream("/in.txt"),"UTF-8");
PrintWriter out = new PrintWriter("/out.txt")){
while (in.hasNext())
out.println(in.next().toUpperCase());
}catch (FileNotFoundException ex){
ex.printStackTrace();
}
}

//反编译后得到
public static void main(String[] var0) {
try {
Scanner var1 = new Scanner(new FileInputStream("/in.txt"), "UTF-8");
Throwable var2 = null;

try {
PrintWriter var3 = new PrintWriter("/out.txt");
Throwable var4 = null;

try {
while(var1.hasNext()) {
var3.println(var1.next().toUpperCase());
}
} catch (Throwable var29) {
var4 = var29;
throw var29;
} finally {
if (var3 != null) {
if (var4 != null) {
try {
var3.close();
} catch (Throwable var28) {
var4.addSuppressed(var28);
}
} else {
var3.close();
}
}

}
} catch (Throwable var31) {
var2 = var31;
throw var31;
} finally {//编译器自动生成资源关闭操作
if (var1 != null) {
if (var2 != null) {
try {
var1.close();
} catch (Throwable var27) {
var2.addSuppressed(var27);
}
} else {
var1.close();
}
}

}
} catch (FileNotFoundException var33) {
var33.printStackTrace();
}
}

参考博客和文章书籍等:

《Java核心技术 卷Ⅱ》

https://mp.weixin.qq.com/s/6dqFNzfSe88vYMW_r3s3Bw

因博客主未标明不可转载,若内容涉及侵权请及时告知,我会尽快修改和删除相关内容