Java lambda 中的异常


Java引入了检查异常的概念。与早期的方法相比,强制开发人员管理异常的想法是革命性的。

如今,Java仍然是唯一提供检查异常的广泛语言。例如,Kotlin 中的每个异常都是未选中的。

即使在 Java 中,新功能也与检查异常不一致:Java 内置函数接口的签名不使用异常。当在 lambda 中集成遗留代码时,它会导致繁琐的代码。这在流中很明显。

在这篇文章中,我想更深入地探讨如何管理这些问题。

代码中的问题

下面是说明该问题的示例代码:

Stream.of("java.lang.String", "ch.frankel.blog.Dummy", "java.util.ArrayList")
      .map(it -> new ForNamer().apply(it))                                     // 1
      .forEach(System.out::println);
  1. 不编译:需要捕获检查ClassNotFoundException

我们必须添加一个 try/catch 块来解决编译问题。

Stream.of("java.lang.String", "ch.frankel.blog.Dummy", "java.util.ArrayList")
      .map(it -> {
          try {
              return Class.forName(it);
          } catch (ClassNotFoundException e) {
              throw new RuntimeException(e);
          }
      })
      .forEach(System.out::println);

添加块违背了易于阅读的管道的目的。

将 try/catch 块封装到一个类中

为了恢复可读性,我们需要重构代码以引入一个新类。IntelliJ IDEA甚至提出了一个记录:

var forNamer = new ForNamer();                                                // 1
Stream.of("java.lang.String", "ch.frankel.blog.Dummy", "java.util.ArrayList")
      .map(forNamer::apply)                                                   // 2
      .forEach(System.out::println);

record ForNamer() implements Function<String, Class<?>> {

    @Override
    public Class<?> apply(String string) {
        try {
            return Class.forName(string);
        } catch (ClassNotFoundException e) {
            return null;
        }
    }
}
  1. 创建单个记录对象
  2. 重用它

尝试龙目岛

Project Lombok 是一个编译时注释处理器,可生成额外的字节码。一个人使用正确的注释并获得结果,而无需编写样板代码。

Project Lombok 是一个 Java 库,它会自动插入编辑器和构建工具,为您的 Java 增添趣味。永远不要再写另一个 getter 或 equals 方法,使用一个注释,您的类有一个功能齐全的构建器,自动化您的日志记录变量等等。

— 龙目岛计划

Lombok 提供了注释:它允许人们抛出检查的异常,而无需在自己的方法签名中声明它们。然而,它目前不适用于现有的 API。@SneakyThrow

如果您是龙目岛用户,请注意,状态为停放时存在打开的 GitHub 问题

下议院朗来救援

Apache Commons Lang是一个古老的项目。它在当时很普遍,因为它提供了可能是Java API的一部分但不是的实用程序。这是一个比在每个项目中重新发明你的兰德更好的选择。在研究这篇文章时,我发现它仍然定期使用出色的 API 进行维护,其中之一是 API。DateUtilsStringUtilsFailable

该 API 由两部分组成:

  1. 围绕Stream
  2. 签名接受异常的管道方法

这里有一个小摘录:

可失败的 API 摘录

代码最终成为我们从一开始就期望的:

Stream<String> stream = Stream.of("java.lang.String", "ch.frankel.blog.Dummy", "java.util.ArrayList");
Failable.stream(stream)
        .map(Class::forName)                                                  // 1
        .forEach(System.out::println);

修复编译时错误是不够的

前面的代码在 anat运行时中抛出 awrack。我们对编译器感到满意,但我们无法指定预期的行为:ClassNotFoundExceptionUndeclaredThrowableException

  • 抛出第一个异常
  • 丢弃异常
  • 聚合类和异常,以便我们可以在管道的最后阶段对它们采取行动
  • 别的

为了实现这一目标,我们可以利用Vavr的力量。Vavr是一个将函数式编程的强大功能引入Java语言的库:

Vavr core是一个Java函数库。它有助于减少代码量并提高健壮性。函数式编程的第一步是开始思考不可变的值。Vavr 提供不可变的集合以及必要的函数和控制结构来操作这些值。结果是美丽的,只是工作。

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/292589.html

(0)
上一篇 2022年11月4日
下一篇 2022年11月4日

相关推荐

发表回复

登录后才能评论