我希望使我的代码更具可读性,并使用 IDE 代码检查和/或静态代码分析(FindBugs 和 Sonar)等工具来避免 NullPointerExceptions。许多工具似乎彼此不兼容 @NotNull
/ @NonNull
/ @Nonnull
注释并在我的代码中列出所有这些注释并在我的代码中列出所有这些会很糟糕。关于哪一个是“最好的”的任何建议?这是我找到的等效注释列表:
javax.validation.constraints.NotNull
创建用于运行时验证,而不是静态分析。
edu.umd.cs.findbugs.annotations.NonNull
由 FindBugs ( 已死项目)及其后继 SpotBugs 静态分析以及因此 Sonar(现为 Sonarqube )使用
javax.annotation.Nonnull
这可能也适用于 FindBugs,但 JSR-305 是不活动的。 (另请参阅: JSR 305 的状态是什么? ) 来源
org.jetbrains.annotations.NotNull
由 IntelliJ IDEA IDE 用于静态分析。
lombok.NonNull
用于控制 Project Lombok 中的代码生成。
占位符注释,因为没有标准。
androidx.annotation.NonNull
Android 中可用的标记注解,由注解包提供
org.eclipse.jdt.annotation.NonNull
由 Eclipse 用于静态代码分析
原文由 jaxzin 发布,翻译遵循 CC BY-SA 4.0 许可协议
由于 JSR 305 (其目标是标准化
@NonNull
和@Nullable
)已经休眠了好几年,恐怕没有好的答案。我们所能做的就是找到一个务实的解决方案,我的解决方案如下:句法
从纯粹的风格角度来看,我想避免提及 IDE、框架或除 Java 本身之外的任何工具包。
这排除了:
android.support.annotation
edu.umd.cs.findbugs.annotations
org.eclipse.jdt.annotation
org.jetbrains.annotations
org.checkerframework.checker.nullness.qual
lombok.NonNull
这给我们留下了
javax.validation.constraints
或javax.annotation
。前者随 JEE 一起提供。如果这比javax.annotation
更好,这可能最终会出现在 JSE 中,或者根本不会出现,这是一个有争议的问题。我个人更喜欢javax.annotation
因为我不喜欢 JEE 依赖项。这给我们留下了
javax.annotation
这也是最短的。
只有一种语法会更好:
java.annotation.Nullable
。随着其他软件包在过去从javax
升级到java
,javax.annotation 将是朝着正确方向迈出的一步。执行
我希望它们都有基本相同的简单实现,但详细分析表明这不是真的。
首先是相同点:
@NonNull
注释都有一行除了
org.jetbrains.annotations
调用它@NotNull
并有一个简单的实现javax.annotation
实现时间更长javax.validation.constraints
也叫它@NotNull
并且有一个实现@Nullable
注释都有一行除了(再次)
org.jetbrains.annotations
及其简单的实现。对于差异:
一个引人注目的是
javax.annotation
javax.validation.constraints
org.checkerframework.checker.nullness.qual
都有运行时注释(
@Retention(RUNTIME)
),而android.support.annotation
edu.umd.cs.findbugs.annotations
org.eclipse.jdt.annotation
org.jetbrains.annotations
只是编译时间(
@Retention(CLASS)
)。如 本 SO 回答 中所述,运行时注释的影响比人们想象的要小,但它们的好处是使工具能够在编译时检查之外进行运行时检查。
另一个重要的区别是可以在代码中的什么 地方 使用注释。有两种不同的方法。一些包使用 JLS 9.6.4.1 样式上下文。下表给出了一个概览:
包裹场地方法范围本地变量android.support.annotation ✔️ ✔️ ✔️ edu.umd.cs.findbugs.注释✔️ ✔️ ✔️ ✔️ org.jetbrains.注释✔️ ✔️ ✔️ ✔️龙目岛✔️ ✔️ ✔️ ✔️ javax.validation.constraints ✔️ ✔️ ✔️
org.eclipse.jdt.annotation
,javax.annotation
和org.checkerframework.checker.nullness.qual
使用 JLS 4.11 中定义的上下文,我认为这是正确的做法。这给我们留下了
javax.annotation
org.checkerframework.checker.nullness.qual
在这一轮中。
代码
为了帮助您自己比较更多细节,我在下面列出了每个注释的代码。为了便于比较,我删除了注释、导入和
@Documented
注释。 (他们都有@Documented
除了Android包中的类)。我重新排序了行和@Target
字段并对资格进行了规范化。为了完整起见,这里是
@Nullable
实现:下面两个包没有
@Nullable
,所以单独列出来;龙目岛有一个很无聊的@NonNull
。在javax.validation.constraints
@NonNull
实际上是一个@NotNull
它有一个较长的实现。支持
根据我的经验,
javax.annotation
至少得到 Eclipse 和开箱即用的 Checker Framework 的支持。概括
我理想的注释是
java.annotation
带有 Checker Framework 实现的语法。如果您不打算使用 Checker Framework,那么
javax.annotation
( JSR-305 ) 目前仍然是您最好的选择。如果您愿意购买 Checker Framework,只需使用他们的
org.checkerframework.checker.nullness.qual
。来源
android.support.annotation
来自android-5.1.1_r1.jar
edu.umd.cs.findbugs.annotations
来自findbugs-annotations-1.0.0.jar
org.eclipse.jdt.annotation
来自org.eclipse.jdt.annotation_2.1.0.v20160418-1457.jar
org.jetbrains.annotations
来自jetbrains-annotations-13.0.jar
javax.annotation
来自gwt-dev-2.5.1-sources.jar
org.checkerframework.checker.nullness.qual
来自checker-framework-2.1.9.zip
lombok
来自lombok
提交f6da35e4c4f3305ecd1b415e2ab1b9ef8a9120b4
javax.validation.constraints
来自validation-api-1.0.0.GA-sources.jar