java nonnull annotation




我應該使用哪個@NotNull Java註釋? (13)

Android的

這個答案是Android特有的。 Android有一個名為support-annotations支持包。 這提供了dozens http://tools.android.com/tech-docs/support-annotations註釋,並且還提供了像NonNullNullable常見的註釋。

要添加support-annotations包,請在build.gradle中添加以下依賴項:

compile 'com.android.support:support-annotations:23.1.1'

然後使用:

import android.support.annotation.NonNull;

void foobar(@NonNull Foo bar) {}

我期望讓代碼更具可讀性,並使用IDE代碼檢查和/或靜態代碼分析(FindBugs和Sonar)等工具來避免NullPointerException。 許多工具似乎與其他人的@NotNull / @NonNull / @Nonnull註解不兼容,並且在我的代碼中列出所有這些工具會非常糟糕。 任何建議哪一個是'最好的'? 以下是我找到的等效註釋列表:



Another option is the annotations provided with ANTLR 4. Following Pull Request #434 , the artifact containing the @NotNull and @Nullable annotations includes an annotation processor that produces compile-time errors and/or warnings in the event one of these attributes is misused (for example, if both are applied to the same item, or if @Nullable is applied to item with a primitive type). The annotation processor provides additional assurance during the software development process that the information conveyed by the application of these annotations is accurate, including in cases of method inheritance.


Distinguish between static analysis and runtime analysis. Use static analysis for internal stuff, and runtime analysis for the public boundaries of your code.

For things that should not be null:

  • Static check: Use @javax.annotations.Nonnull
  • Runtime check: Use "if (x == null) ..." (zero dependency) or @javax.validation.NotNull (with bean validation) or @lombok.NonNull (plain and simple) or guavas Preconditions.checkNotNull(...)
  • Where it fits, use @...NonnullByDefault annotations on class or package level. Create these annotations yourself (examples are easy to find).

For things that may be null (No runtime check required):

  • Use Optional for method return types (only). Either Java8 or Guava.
  • Else, use @javax.annotation.CheckForNull to avoid NPEs

This should give the best result: warnings in the IDE, errors by Findbugs and checkerframework, meaningful runtime exceptions.

Some explanations:

  • jetbrains, eclipse or checkersframework annotations for static checking have no advantage over javax.annotations. jetbrains @NotNull name conflicts with @javax.validation.NotNull.
  • @javax.annotations.Nullable does not mean what you (or your IDE) think it means. Findbugs will ignore it (on members). Sad, but true.
  • For @javax.annotations.CheckForNull, you may have to configure your IDE, or else use it in combination with @javax.annotations.Nullable
  • For static checking, 2 free tools exist: Findbugs and checkersframework.
  • The Eclipse library has @NonNullByDefault, jsr305 only has @ParametersAreNonnullByDefault. Those are mere convenience wrappers applying base annotations to everythin in a package (or class), you can easily create your own. This can be used on package. This may conflict with generated code (eg lombok).
  • Using lombok as an exported dependency should be avoided for libraries that you share with other people, the less transitive dependencies, the better
  • Using Bean validation framework is powerful, but requires high overhead, so that's overkill just to avoid manual null checking.
  • Using Optional for fields and method parameters is controversial (you can find articles about it easily)
  • I don't know about Android, check other answers

不幸的是, JSR 308不會在這裡添加比這個項目的Local Null建議更多的值

Java 8不會附帶單個默認註釋或其自己的Checker框架。 類似於Find-bugs或JSR 305 ,這個JSR很少被一小群大多數學術團隊維護。

沒有商業力量,因此JSR 308推出EDR 3JCP早期草稿審核),而Java 8應該在不到6個月的時間內發布:-O類似於310 btw。 但與308 Oracle不同的是, 308 Oracle公司現在已經遠離創始人負責,以盡量減少對Java平台造成的損害。

Checker FrameworkJSR 308類的每個項目,供應商和學術類都將創建自己的專有檢查器註釋。

使源代碼在未來幾年不兼容,直到可以找到一些常見的妥協方案,並且可能將其添加到Java 910 ,或通過Apache CommonsGoogle Guava等框架;-)


只需指出Java驗證API( javax.validation.constraints.* )不帶有@Nullable註釋,這在靜態分析上下文中非常有用。 它對於運行時bean驗證是有意義的,因為這是Java中任何非原始字段的默認值(即沒有任何驗證/強制執行)。 出於所述的目的應該考慮替代方案。


如果任何人只是在尋找IntelliJ類:你可以從Maven倉庫獲取它們

<dependency>
    <groupId>org.jetbrains</groupId>
    <artifactId>annotations</artifactId>
    <version>15.0</version>
</dependency> 

如果你正在為android開發,你會綁定到Eclipse上(編輯:在寫作時,不再是),它有自己的註釋。 它包含在Eclipse 3.8+(Juno)中,但默認禁用。

您可以在首選項> Java>編譯器>錯誤/警告>空分析(底部的可折疊部分)中啟用它。

選中“啟用基於註釋的空分析”

http://wiki.eclipse.org/JDT_Core/Null_Analysis#Usage有關於設置的建議。 但是,如果您的工作空間中有外部項目(如Facebook SDK),則可能無法滿足這些建議,並且您可能不希望用每個SDK更新修復它們;-)

我用:

  1. 空指針訪問:錯誤
  2. 違反空指定:錯誤(鏈接到點#1)
  3. 潛在的空指針訪問:警告(否則Facebook SDK會有警告)
  4. 空註釋和空推斷之間的衝突:警告(鏈接到點#3)

對於Android項目,您應該使用android.support.annotation.NonNullandroid.support.annotation.Nullable支持庫中提供了這些以及其他有用的Android特定註釋。

http://tools.android.com/tech-docs/support-annotations

支持庫本身也被註釋了這些註釋,因此作為支持庫的用戶,Android Studio將已經檢查您的代碼並根據這些註釋標記潛在的問題。


我使用IntelliJ,因為我主要關注IntelliJ標記可能產生NPE的事情。 我同意在JDK中沒有標準註釋讓人感到沮喪。 有關於添加它的討論,它可能會使它成為Java 7.在這種情況下,將會有更多的選擇!


根據Java 7特性列表, JSR-308類型註釋被推遲到Java 8.甚至沒有提到JSR-305註釋。

有關最新JSR-308草案appendix中JSR-305狀態的信息。 這包括JSR-305註釋似乎被放棄的觀察。 JSR-305頁面也顯示它為“不活動”。

同時,實用的答案是使用最廣泛使用的工具支持的註釋類型......並準備在情況發生變化時對其進行更改。

事實上,JSR-308沒有定義任何註釋類型/類,看起來他們認為它超出了範圍。 (鑑於JSR-305的存在,它們是正確的)。

但是,如果JSR-308真的看起來像將其加入到Java 8中,那麼對JSR-305的興趣就會恢復,這並不會讓我感到意外。 AFAIK,JSR-305團隊尚未正式放棄他們的工作。 他們已經安靜了2年。

有趣的是,Bill Pugh(JSR-305的技術負責人)是FindBugs背後的人之一。



還有另外一種方法可以在Java 8中完成這項工作。我正在做兩件事來完成我所需要的:

  1. 通過使用java.util.Optional封裝可空字段來將空值字段用類型顯式化
  2. 使用java.util.Objects.requireNonNull檢查所有不可為空的字段在構造時是否為空

例:

import static java.util.Objects.requireNonNull;

public class Role {

  private final UUID guid;
  private final String domain;
  private final String name;
  private final Optional<String> description;

  public Role(UUID guid, String domain, String name, Optional<String> description) {
    this.guid = requireNonNull(guid);
    this.domain = requireNonNull(domain);
    this.name = requireNonNull(name);
    this.description = requireNonNull(description);
  }

所以我的問題是,我們甚至需要使用java 8註釋嗎?

編輯:我後來發現,有些人認為在參數中使用Optional是一種不好的做法,這裡有一個很好的討論,討論了優缺點為什麼應該在參數中使用Java 8的Optional





ide