你不讨厌你必须用静态初始化器来包装检查异常的代码吗?例如,你不能在Java中这样写:
public class Test {
static final Class<?> klass = Class.forName("org.h2.Driver");
}
有一个未处理的ClassNotFoundException
,你不能简单地捕捉/重新抛出它。需要一个静态初始化器:
public class Test {
static final Class<?> klass;
static {
try {
klass = Class.forName("org.h2.Driver");
}
catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
幸运的是,jOOλ的 一个不太为人所知的功能是 [Sneaky](https://www.jooq.org/products/jOO%CE%BB/javadoc/latest/org/jooq/lambda/Sneaky.html)
类,它包含了一堆实用的方法,可以将JDK的功能接口包装成一个等价的、"偷偷抛出 "的功能接口,不需要声明被检查的异常。
简而言之,你可以这样写:
public class Test {
static final Class<?> klass = Sneaky.supplier(
() -> Class.forName("org.h2.Driver")
).get();
}
异常被 "偷偷 "地重新抛出,因为JVM并不关心一个异常的检查性。如果你的classpath上没有H2,你会得到:
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.ClassNotFoundException: org.h2.Driver
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:375)
at org.jooq.test.util.Test.lambda$0(Test.java:44)
at org.jooq.lambda.Unchecked.lambda$supplier$38(Unchecked.java:1695)
at org.jooq.test.util.Test.<clinit>(Test.java:44)
你可以在其他需要JDK功能接口的地方使用这种方法,而且你不关心异常的检查性,例如在流中:
// Doesn't compile:
Stream
.generate(
() -> Class.forName("org.h2.Driver"))
.limit(1)
.forEach(System.out::println);
// So ugly
Stream
.generate(
() -> {
try {
return Class.forName("org.h2.Driver");
}
catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
})
.limit(1)
.forEach(System.out::println);
// Use jOOλ's Sneaky supplier
Stream
.generate(Sneaky.supplier(
() -> Class.forName("org.h2.Driver")))
.limit(1)
.forEach(System.out::println);
在这里获取jOOλ:https://github.com/jOOQ/jOOL