前言
Java编译中的异常主要分为两类:
- 受查异常,是指编译器要求必须处理的异常,否则编译不通过。
比如IOException及其子类,ClassNotFoundException、FileNotFoundException等。
2. 非受查异常,是指编译器不强制要求处理的异常,可能会在运行时抛出。
比如NullPointerException、ArrayIndexOutOfBoundsException等。
场景
受查异常的设计目的是为了提醒开发者这里会发生异常,必须显示处理这些异常。
比如下面的new String()
方法会抛出IO异常,我们要么使用try catch
处理,要么就抛出异常。
1 | java复制代码// 抛出异常会使代码变长,好处是能明显看出异常类型 |
牛逼的地方来了,我们可以使用@SneakcyThrows
来代替上面抛出异常的形式:
1 | java复制代码// 干净清爽 |
所以,@SneakyThrows
可用于在不声明throws的情况下偷偷地抛出已检查的异常。
注意!Lombok生成的代码并不会忽略,包装,替换或以其他方式修改引发的检查异常,该抛出什么还是会抛出什么。它只是骗过了编译器,这样javac就不会报错了。
原理
为什么@SneakyThrows可以骗过编译器?
实际上,编译过后的类长这样:
1 | java复制代码public String utf8ToString(byte[] bytes) { |
我们看一下Lombok.sneakyThrow(e)
方法:
1 | java复制代码// JVM实际上并不了解或关心 "检查异常 "的概念 |
这个方法的核心逻辑是throw (T)t
,利用泛型将父类型Throwable
转换为子类型RuntimeException
。
虽然事实上它不是RuntimeException
,这样写只是为了骗过javac编译器,由于泛型擦除,实际并没有转换类型,而且JVM压根不关心这个,抛异常就是抛异常,不区分受查/非受查。
总结
@SneakyThrows
不是万金油,应当谨慎使用。
Lombok一直以来都备受争议,有人觉得自动生成代码很方便,有人觉得是一种破坏。
个人认为只要开发团队达成共识,Lombok可以一定程度上提升代码可读性和开发效率。
本文转载自: 掘金