为什么要使用 Lombok-Annotation @NonNull?

Why would I use Lombok-Annotation @NonNull?

Lombok 提供 annotation @NonNull 执行 nullcheck 并抛出 NPE(如果配置不同)。

我不明白为什么我会使用该文档 example 中所述的注释:

private String name;
public NonNullExample(@NonNull Person person) {
    super("Hello");
    if (person == null) {
      throw new NullPointerException("person is marked @NonNull but is null");
    }
    this.name = person.getName();
  }

无论如何都会抛出NPE。此处使用注释 imo 的唯一原因是您是否希望异常与 NPE 不同。

编辑:我知道异常会被显式抛出,因此 'controlled',但至少错误消息的文本应该是可编辑的,不是吗?

注释的想法是避免代码中的 if (person == null) 并使代码更简洁。

恕我直言,你理解错了that documentation page

该文档页面并不暗示建议您同时使用 Lombok @NonNull 注释和显式 if (smth == null) throw … 类检查(用同样的方法)。

它只是说像这样的代码(我们称它为代码A):

import lombok.NonNull;

public class NonNullExample extends Something {
  private String name;

  public NonNullExample(@NonNull Person person) {
    super("Hello");
    this.name = person.getName();
  }
}

将由 Lombok 自动(内部)翻译成类似于引用问题的代码(我们称之为 code B)。

但是该文档页面并未说明显式编写 代码 B 是有意义的(尽管您被允许;并且 Lombok 甚至会尝试防止双重检查这种情况)。它只是说使用 Lombok 您现在可以编写 代码 A(以及 它将如何工作 — 它将隐式转换为 代码 B).

请注意,代码 B 是“普通 Java”代码。预计不会由 Lombok 第二次处理。所以 代码 B 中的 @NonNull 只是一个普通的注释,它对行为没有影响(至少,不是 Lombok 的意思)。

为什么 Lombok 以这种方式工作是一个单独的问题 — 为什么它不从生成的代码中删除 @NonNull。最初,我什至 thought that it might be a bug in that documentation page. But, as Lombok author explains in his comment@NonNull 都是有意保留的,以供其他工具进行文档和可能的处理。

它的用途与

相似

java.util.Objects requireNonNull()

或者 Guava 的先决条件。这只是让代码更加紧凑和fail-fast。

编写类型注释,例如 @NonNull 有多种用途。

  • 它是文档:它以比 Javadoc 文本更简洁和精确的方式将方法的契约传达给客户。
  • 它启用 run-time 检查 -- 也就是说,如果客户端有问题,它保证您的程序崩溃并显示有用的错误消息(而不是做更糟糕的事情) mis-uses 你的方法。 Lombok 会为您完成此操作,而无需强制程序员编写 run-time 检查。 referenced example 显示了执行此操作的两种方法:使用单个 @NonNull 注释或使用显式 programmer-written 检查。 "Vanilla Java" 版本要么有拼写错误(误读 @NonNull),要么在 Lombok 处理后显示代码。
  • 启用compile-time检查。像 Checker Framework gives a guarantee that the code will not crash at run time. Tools such as NullAway, Error Prone, and FindBugs 这样的工具是启发式的 bug-finders,它会警告您一些 mis-uses 为 null 但不给您保证。

我喜欢龙目岛,但在这种情况下(个人)我更喜欢使用来自 javax.annotation@Nonnull 注释和来自 Objects.requireNonNull java.util.Objects

以这种方式使用 lombok 使代码更清晰,但更不清晰和可读:

public Builder platform(@NonNull String platform) {
    this.platform = platform;
    return this;
}  

此方法引发 NullPointerException(没有证据表明)并且上瘾 我的 IDE 未报告在方法调用中传递空参数(IntelliJ Ultimate 2020.1 EAP - 最新版本 - 带有 lombok 插件)


所以我更喜欢以这种方式使用 javax.annotation 中的 @Nonnull 注释:

public Builder platform(@Nonnull String platform) {
    this.platform = Objects.requireNonNull(platform);
    return this;
}

代码有点冗长但更清晰,如果我在方法调用中传递空参数,我的 IDE 能够警告我!