Java异常处理三

Java异常处理三

在前文Java异常处理一中有介绍java中我们常见的2类异常:

  1. 普通Exception类,也就是我们常说的受检异常或者Checked Exception。
  2. RuntimeException类,即运行时异常。

前者会强制要求抛出它的方法声明throws,调用者必须显式地去处理这个异常。设计的目的是为了提醒开发者处理一些场景中必然可能存在的异常情况。比如网络异常造成IOException。

但是现实,往往事与愿违。大部分情况下的异常,我们都是一路往外抛。所以渐渐的java程序员处理Exception的常见手段就是外面包一层RuntimeException,接着往上丢。这种解决思想尤其在Spring中到处出现。

1
2
3
4
5
try{

}catch(Exception e){
throw new RuntimeException(e);
}

或者更像JDK中的一些实现。

1
2
3
4
5
6
7
8
9
10
11
// ForkJoinTask.java
static void rethrow(Throwable ex) {
if (ex != null)
ForkJoinTask.<RuntimeException>uncheckedThrow(ex);
}

@SuppressWarnings("unchecked")
static <T extends Throwable>
void uncheckedThrow(Throwable t) throws T {
throw (T)t; // rely on vacuous cast
}

利用泛型将我们传入的Throwable强转为RuntimeException。虽然事实上我们不是RuntimeException。但是没关系。因为JVM并不关心这个。泛型最后存储为字节码时并没有泛型的信息。这样写只是为了骗过javac编译器(注意@SuppressWarnings("unchecked"))。

Lombok的@SneakyThrows就是为了消除这样的模板代码。使用注解后不需要担心Exception的处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
import lombok.SneakyThrows;

public class SneakyThrowsExample implements Runnable {
@SneakyThrows(UnsupportedEncodingException.class)
public String utf8ToString(byte[] bytes) {
return new String(bytes, "UTF-8");
}

@SneakyThrows
public void run() {
throw new Throwable();
}
}

真正生成的代码:

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 SneakyThrowsExample implements Runnable {
public String utf8ToString(byte[] bytes) {
try {
return new String(bytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw Lombok.sneakyThrow(e);
}
}

public void run() {
try {
throw new Throwable();
} catch (Throwable t) {
throw Lombok.sneakyThrow(t);
}
}
}
// ---------------------- sneakyThrow ----------------------------
public static RuntimeException sneakyThrow(Throwable t) {
if (t == null) throw new NullPointerException("t");
return Lombok.<RuntimeException>sneakyThrow0(t);
}

private static <T extends Throwable> T sneakyThrow0(Throwable t) throws T {
throw (T)t;
}
-------------本文结束感谢您的阅读-------------
坚持分享,您的支持将鼓励我继续创作!
0%