使用Optional.map()而不是Optional.ifPresent()来执行可能会引发异常并返回任何异常作为返回值的代码

问题描述 投票:1回答:2

我正在尝试使用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();
    }
}

还有更好的选择吗?

java exception optional
2个回答
0
投票

编辑:如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推断为RuntimeExceptionError),它可以编译而不会出现错误,但仍像您实际说的throw e一样运行。

public static <T extends Throwable> void sneakyThrow(Throwable t) throws T {
    throw (T) t;
}

Lombok具有SneakyThrows注释可以帮助您完成此操作。

这样,您不必将其包装在RuntimeException或其他任何东西中-例外也是在运行时也只是IOException


0
投票

我认为这不是使用Optional的正确位置,而您还有其他可以处理您所寻找的相同问题的类。

© www.soinside.com 2019 - 2024. All rights reserved.