简体   繁体   English

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

[英]Why would I use Lombok-Annotation @NonNull?

Lombok offers the annotation @NonNull which executes the nullcheck and throws a NPE (if not configured differently). Lombok 提供了@NonNull注释,它执行空检查并抛出一个 NPE(如果没有以不同的方式配置)。

I do not understand why I would use that annotation as described in the example of that documentation:我不明白为什么我会使用该文档示例中所述的注释:

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();
  }

The NPE would be thrown anyway.无论如何都会抛出 NPE。 The only reason here to use the annotation imo is if you would want the exception to be different from a NPE.此处使用注释 imo 的唯一原因是您是否希望异常与 NPE 不同。

EDIT: I do know that the Exception would be thrown explicitly and thus 'controlled', but at least the text of the error message should be editable, shouldn't it?编辑:我知道异常会被显式抛出并因此被“控制”,但至少错误消息的文本应该是可编辑的,不是吗?

Writing a type annotation such as @NonNull serves several purposes.编写诸如@NonNull类的类型注释有多种用途。

  • It is documentation : it communicates the method's contract to clients, in a more concise and precise way than Javadoc text.它是文档:它以比 Javadoc 文本更简洁和精确的方式将方法的契约传达给客户端。
  • It enables run-time checking -- that is, it guarantees that your program crashes with a useful error message (rather than doing something worse) if a buggy client mis-uses your method.它启用运行时检查——也就是说,如果有错误的客户端误用你的方法,它可以保证你的程序崩溃并显示有用的错误消息(而不是做更糟糕的事情)。 Lombok does this for you, without forcing the programmer to write the run-time check. Lombok 会为您执行此操作,而无需强制程序员编写运行时检查。 The referenced example shows the two ways to do this: with a single @NonNull annotation or with an explicit programmer-written check.引用的示例显示了执行此操作的两种方法:使用单个@NonNull注释或使用显式程序员编写的检查。 The "Vanilla Java" version either has a typo (a stray @NonNull ) or shows the code after Lombok processes it. “Vanilla Java”版本要么有拼写错误(错误的@NonNull ),要么在 Lombok 处理后显示代码。
  • It enables compile-time checking .它启用编译时检查 A tool such as the Checker Framework gives a guarantee that the code will not crash at run time. Checker Framework等工具可以保证代码在运行时不会崩溃。 Tools such as NullAway , Error Prone , and FindBugs are heuristic bug-finders that will warn you about some mis-uses of null but do not give you a guarantee.诸如NullAwayError ProneFindBugs 之类的工具是启发式错误查找器,它们会警告您有关 null 的一些误用,但不给您保证。

IMHO, you've understood that documentation page wrongly.恕我直言,您已经错误地理解了该文档页面

That documentation page doesn't imply that you are recommended to use both Lombok @NonNull annotations and explicit if (smth == null) throw … -like checks as the same time (in the same method).该文档页面并不意味着建议您同时使用 Lombok @NonNull注释和显式if (smth == null) throw … -like 检查(以相同的方法)。

It just says that a code like this one (let's call it code A ):它只是说这样的代码(我们称之为代码 A ):

import lombok.NonNull;

public class NonNullExample extends Something {
  private String name;

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

will be automatically (internally) translated by Lombok into a code like the one quoted the question (let's call it code B ).将被 Lombok 自动(内部)翻译成一个代码,就像引用问题的代码一样(我们称之为代码 B )。

But that documentation page doesn't say that it would make sense for you to explicitly write the code B (though you are allowed; and Lombok will even try to prevent double check in this case).但是该文档页面并没有说您明确编写代码 B是有意义的(尽管您被允许;在这种情况下,Lombok 甚至会尝试防止双重检查)。 It just says that with Lombok you are now able to write the code A (and how it will work — it will be implicitly converted into the code B ).它只是说使用 Lombok您现在可以编写代码 A (以及它的工作方式——它将被隐式转换为代码 B )。

Note, that the code B is a “vanilla Java” code.请注意,代码 B是“vanilla Java”代码。 It isn't expected to be processed by the Lombok for the second time.预计龙目岛不会第二次处理它。 So @NonNull in the code B is just a plain annotation, which has no influence on the behavior (at least, not by Lombok means).所以代码 B中的@NonNull只是一个普通的注释,它对行为没有影响(至少,不是龙目岛的方式)。

It's a separate question why Lombok works in that way — why it doesn't remove @NonNull from the generated code.这是一个单独的问题,为什么 Lombok 以这种方式工作 - 为什么它不从生成的代码中删除@NonNull Initially I even thought that it might be a bug in that documentation page.最初我什至认为这可能是该文档页面中的错误。 But, as Lombok author explains in his comment , @NonNull s are intentionally kept for the purposes of documentation and possible processing by other tools.但是,正如 Lombok 作者在他的评论中解释的那样, @NonNull是有意保留的,目的是记录和其他工具可能进行的处理。

I love lombok but in this case (personally) I prefer to use the @Nonnull annotation from javax.annotation with the Objects.requireNonNull from java.util.Objects .我喜欢 lombok 但在这种情况下(个人)我更喜欢使用javax.annotation 中@Nonnull注释和java.util.Objects 中Objects.requireNonNull

Using lombok in this way make the code cleaner but even less clear and readable:以这种方式使用 lombok 会使代码更清晰,但更不清晰和可读:

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

This method raises a NullPointerException (no evidence of it) and in addiction passing a null argument, in a method call, is not reported by my IDE (IntelliJ Ultimate 2020.1 EAP - latest version - with lombok plugin)这个方法引发了一个 NullPointerException(没有证据),并且在方法调用中传递了一个空参数,我的 IDE 没有报告(IntelliJ Ultimate 2020.1 EAP - 最新版本 - 带有 lombok 插件)


So I prefer using the @Nonnull annotation from javax.annotation in this way:所以我更喜欢以这种方式使用javax.annotation中的@Nonnull注释:

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

The code is a little bit verbose but clearer and my IDE is capable to warning me if I pass a null argument on method call!代码有点冗长但更清晰,如果我在方法调用时传递空参数,我的 IDE 能够警告我!

注释的想法是避免代码中的if (person == null)并保持代码清洁。

It serves similar purpose to它用于类似的目的

java.util.Objects requireNonNull()

or Guava's PreConditions.或番石榴的先决条件。 This just makes the code more compact and fail-fast.这只会使代码更加紧凑和快速失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM