@Sneaky Throws 在龙目岛的应用

Posted

技术标签:

【中文标题】@Sneaky Throws 在龙目岛的应用【英文标题】:Application of @Sneaky Throws in lombok 【发布时间】:2021-01-20 07:53:57 【问题描述】:

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

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

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

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

【问题讨论】:

【参考方案1】:

添加到现有答案。我个人不喜欢检查异常。查看更多信息: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();

相对于非@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());

因此,@SneakyThrows 的应用使代码更加简洁。

【讨论】:

【参考方案2】:

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

例如,如果方法是

public void throwsCheckedException() 
    throw new IOException("IO exception thrown");

这会导致编译时异常需要

public void throwsCheckedException() throws IOException 
    throw new IOException("IO exception thrown");

注释@SneakThrows 缓解了这一点 - 声明为的原始方法

@SneakyThrows
public void throwsCheckedException() 
    throw new IOException("IO exception thrown");

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

【讨论】:

你的意思只是从方法声明中删除 throws,我们使用它,对吧? 这意味着该方法的任何调用者都不会意识到异常被显式抛出,并且不需要显式添加 try-catch 块或 throws 到该方法声明。我希望这是有道理的? 评论更有意义。【参考方案3】:

在 JAVA 8 及以上版本中使用 lambda 时尤其不方便使用。

    主要考虑将它用于旧版本的 Java 8。 目的本身就是为了警告而故意抛出异常。通过这个,其他服务/程序/代码可以识别应该如何处理请求/响应流。如果您已经有了适当的机制,则无需担心。

@SneakyThrows 在当前的传统应用程序开发中没有多大用处,可用于某种状态机程序中,在这些程序中,有必要(虽然我没有这方面的专业知识)来确定程序当前流程的状态.这只是不同场景的 1 个示例,可能还有更多。

【讨论】:

恕我直言,这个答案没有多大意义:什么是“它”和“它自己”?什么是“Java 8 的旧版本”(与“Java 8 的新版本”相比?)什么是“某种状态机程序”,它们与 @SneakyThrows 有什么关系?

以上是关于@Sneaky Throws 在龙目岛的应用的主要内容,如果未能解决你的问题,请参考以下文章

龙目岛如何运作?

龙目岛建设者的继承

如何抑制龙目岛警告

龙目岛与休眠

不能让杰克逊和龙目岛一起工作

Quarkus 和 Jackson 奇怪的龙目岛行为