我正在尝试使用java.util.Optional
类的正确方法。给出以下示例代码:
public void doSomething(File destDir, String classifier) throws IOException {
URL resourceRoot = introspectionService.getResourceRoot(pattern);
if (resourceRoot != null) {
JarFile jarFile = (JarFile) resourceRoot.getContent(); //this can throw IOException
... snipped for brevity ...
}
}
我想将此方法转换为使用来自introspectionService的Optional<URL>
值。
public void doSomething(File destDir, String classifier) throws IOException {
Optional<URL> resourceRoot = introspectionService.getResourceRoot(pattern);
resourceRoot.ifPresent(rootUrl-> {
JarFile jarFile = (JarFile) rootUrl.getContent(); //this can throw IOException
... snipped for brevity ...
});
}
这显然无法编译,因为ifPresent()的签名使用了Consumer,该Consumer不允许从accept()方法引发异常。
我想出了以下解决方法,想知道是否有更好的方法:
public void doSomething(File destDir, String classifier) throws IOException {
Optional<URL> resourceRoot = introspectionService.getResourceRoot(pattern);
Optional<IOException> ioException =
resourceRoot.map(rootUrl-> {
try {
JarFile jarFile = (JarFile) rootUrl.getContent(); //this can throw IOException
... snipped for brevity ...
return null;
}
catch(IOException e) {
return e;
}
});
if (ioException.isPresent()) {
throw ioException.get();
}
}
还有更好的选择吗?
编辑:如MC Emperor所建议,您可以抓住IOException
,然后抛出UncheckedIOException
。
这是一种更通用的方法,通过使编译器认为已检查的异常确实未被检查。
resourceRoot.map(rootUrl-> {
try {
JarFile jarFile = (JarFile) rootUrl.getContent(); //this can throw IOException
... snipped for brevity ...
return null;
}
catch(IOException e) {
sneakyThrow(e);
}
});
您可以按如下所示定义sneakyThrow
(我从this文章中获得了它)。由于类型擦除和类型推断(T
推断为RuntimeException
或Error
),它可以编译而不会出现错误,但仍像您实际说的throw e
一样运行。
public static <T extends Throwable> void sneakyThrow(Throwable t) throws T { throw (T) t; }
Lombok具有
SneakyThrows
注释可以帮助您完成此操作。
这样,您不必将其包装在RuntimeException
或其他任何东西中-例外也是在运行时也只是IOException
。
我认为这不是使用Optional
的正确位置,而您还有其他可以处理您所寻找的相同问题的类。