@Sneaky Throws 在 lombok 中的应用

Shi*_*shu 5 java exception lombok checked-exceptions intellij-lombok-plugin

我在使用 Java 中的 Lombok 库时发现了一个名为 @SneakyThrows 的注释。正如文档所述:

@SneakyThrows 伪造了编译器。换句话说,Lombok 不会包装或替换抛出的已检查异常,而是让编译器认为它是未检查异常。

换句话说,这是一种在编译时绕过异常的方法。但在我看来,这不应该是处理异常的正确方法,因为绕过的异常会在运行时表现出奇怪的行为。

那么在哪种情况下应该使用@SneakyThrows?

Mar*_*son 11

我相信这里的目的是使编译器不需要抛出任何异常来添加到方法声明中。

例如,如果该方法是

public void throwsCheckedException() {
    throw new IOException("IO exception thrown");
}
Run Code Online (Sandbox Code Playgroud)

这会导致编译时异常,需要

public void throwsCheckedException() throws IOException {
    throw new IOException("IO exception thrown");
}
Run Code Online (Sandbox Code Playgroud)

注释 @SneakThrows 缓解了这种情况 - 原始方法声明为

@SneakyThrows
public void throwsCheckedException() {
    throw new IOException("IO exception thrown");
}
Run Code Online (Sandbox Code Playgroud)

这不会导致编译时错误。注意 IDE 可能仍会将其突出显示为错误,例如在 IntelliJ 中,您将需要使用 Lombok 插件。

  • 这意味着该方法的任何调用者都不会意识到显式抛出的异常,并且不需要显式添加 try-catch 块或向该方法声明添加 throws。我希望这是有道理的? (5认同)

小智 8

添加到现有答案中。我个人不喜欢检查异常。查看更多信息:https : //phauer.com/2015/checked-exceptions-are-evil/

雪上加霜的是,在避免检查异常时,代码会变得臃肿。考虑@SneakyThrows 的用法:

 List<Instant> instantsSneaky = List.of("2020-09-28T12:30:08.797481Z")
        .stream()
        .map(Example::parseSneaky)
        .collect(Collectors.toList());

@SneakyThrows
private static Instant parseSneaky(String queryValue) {
    return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(queryValue).toInstant();
}
Run Code Online (Sandbox Code Playgroud)

与非@SneakyThrows 相比

 private static Instant parseNonSneaky(String queryValue) throws ParseException {
    return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(queryValue).toInstant();
}

List<Instant> instantsNonSneaky = List.of("2020-09-28T12:30:08.797481Z")
        .stream()
        .map(timeStamp -> {
            try {
                return parseNonSneaky(timeStamp);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
        })
        .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

因此,@SneakyThrows 的应用可以实现更清晰的代码。


Sae*_*and 5

我认为文档对此非常清楚:

当您想要选择退出检查异常机制时,常见用例主要有两种情况:

  1. 不必要的严格接口,例如 Runnable - 无论是否从 run() 方法传播出异常,无论是否检查,它都将传递给线程的未处理异常处理程序。捕获已检查的异常并将其包装在某种 RuntimeException 中只会掩盖问题的真正原因。

  2. 一个“不可能”的例外。例如,new String(someByteArray, "UTF-8"); 声明它可以抛出 UnsupportedEncodingException 但根据 JVM 规范,UTF-8 必须始终可用。当您使用 String 对象时,这里出现 UnsupportedEncodingException 的可能性与 ClassNotFoundError 一样,而且您也不会捕获它们!