java - 我应该使用@NotNull?

  显示原文与译文双语对照的内容

我想让我的代码更具可读性,以及使用IDE代码检查和/或者静态代码分析( FindBugs和声纳) 这样的工具来避免 NullPointerExceptions 。 许多工具似乎与对方的' @NotNull/@NonNull/@NonNull 注释incompatible不兼容,并且在我的代码中列出所有这些工具都是可怕的。 关于哪个是'最佳'的建议? 下面是我找到的等价注释的列表:

  • javax.validation.constraints.NotNull
    为运行时验证创建的,而不是静态分析。
    文档

  • edu.umd.cs.findbugs.annotations.NonNull
    Findbugs静态分析使用的,因此是 Sonar
    文档

  • javax.annotation.Nonnull
    这可能也对Findbugs有用,但JSR-305是不活跃的。

  • com.intellij.annotations.NotNull
    IntelliJ IDEA ide使用静态分析。
    文档

  • lombok.NonNull
    用于控制项目Lombok中的代码生成。
    占位符注释,因为没有标准。
    文档

时间:

我不会使用任何在 javax 命名空间下的任何( 尽管我喜欢Lombok和 IntelliJ ) 。 否则,你可能在创建一个依赖,而不是run-time为你提供的东西,比如语义 。 也许对于一些项目来说,这是可以的,但这对我来说是一个 deal-breaker 。

我将使用 javax.validation.constraints.NotNull 因为已经在这里使用 javaee 6.

javax.annotation.NonNull 在 8 ( 就像Stephen指出的) 之前可能不在这里。 其他的不是标准的注解。

如果注解是可以扩展的,那就再好不过了。 这样你就可以定义你自己的non-null 注解继承/扩展。 然后,当标准被理顺时,你需要做的就是重新定义你自己的自定义注解。

不幸的是,这不是事实。

我非常喜欢检查器框架,它是一个类型注解( JSR-308 )的实现,它用于实现缺陷检查器,如nullness检查器。 我还没有尝试过任何其他的比较,但是我对这个实现很满意。

我不是提供软件的组,但我是一个粉丝。

我喜欢这个系统的四个方面:

  1. 它有一个缺陷的跳棋 nullness ( @Nullable ), 还有的不变性实习 ( 等等) 。 我使用第一个( nullness ),我正在尝试使用第二个( 不可变性/igj ) 。 我正在尝试第三个,但我不确定它是否长期使用。 我还不确定其他跳棋的一般用途,但是很高兴知道框架本身是实现各种附加注解和检查器的系统。

  2. nullness 默认设置的检查工作: Non-null除了局部变量( NNEL ) 之外。这意味着默认情况下,检查器将 everyhing ( 实例变量,方法参数,泛型类型等) 视为局部变量,如同它们在默认情况下具有 @NonNull 类型一样。 根据文档:

    NNEL默认导致代码中的显式注释数最小。

    如果NNEL不工作,则可以为类或者方法设置不同的默认值。

  3. 这个框架允许你使用与 没有创建一个依赖框架 封闭你的注解的评论: 比如 /*@Nullable*/ 。这很好,因为你可以注释和检查一个库或者共享代码,但是仍然可以在其他不使用框架的项目中使用库/共享代码。 这是一个不错的特性。 我已经习惯使用它了,尽管我倾向于在所有的项目中启用检查器框架。

  4. 框架有一种注释api你使用不已经注释nullness通过使用存根文件。

我使用了 IntelliJ,因为我最关心的是IntelliJ标记的事物。 我同意,在JDK中没有标准注释是令人沮丧的。 有关于添加它的讨论,它可能会变成 Java 7. 在这种情况下,还有一个选择 !

根据 7特性列表, JSR-308类型注释被延迟到 Java 8. JSR-305注释没有提到。

上有一些信息状态的JSR-305 附录最新JSR-308草案。 这包括JSR-305注释被放弃的观察。 JSR-305页面也显示为"非活动"。

同时,语用回答是使用最广泛使用的工具所支持的注释类型。 如果情况发生变化,准备更改它们。


事实上,JSR-308没有定义任何注释类型/类,看起来它们已经超出了范围。 ( 鉴于JSR-305的存在,它们是正确的) 。

然而,如果JSR-308真的看起来像成为java 8,我一点也不觉得奇怪,如果兴趣JSR-305恢复。 AFAIK,JSR-305团队还没有正式放弃他们的工作。 他们已经安静了 2年了。

有趣的是,比尔。Pugh ( JSR-305的技术领导者) 是FindBugs幕后的一员。

刚刚指出,Java验证 API ( javax.validation.constraints.* ) 没有一个 @Nullable 注解,它在静态分析环境中非常有用。 它对运行时bean验证有意义,因为这是Java中任何non-primitive字段的默认值( 例如 。 没有什么要验证/实施的。对于声明的目的,应该权衡到替代品。

JSR305和FindBugs是由同一个人编写的。 两者都维护得很差,但它们是标准的,并且被所有主要ide支持。 好消息是他们工作得很好 as-is 。

下面是如何在默认情况下对所有类,方法和字段应用 @Nonnull 。 参见 http://stackoverflow.com 13319541/14731http://stackoverflow.com 9256595/14731

  1. 定义 @NotNullByDefault

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;


/**
 * This annotation can be applied to a package, class or method to indicate that the class fields,
 * method return types and parameters in that element are not null by default unless there is: <ul>
 * <li>An explicit nullness annotation <li>The method overrides a method in a superclass (in which
 * case the annotation of the corresponding parameter in the superclass applies) <li> there is a
 * default parameter annotation applied to a more tightly nested element. </ul>
 * <p/>
 * @see http://stackoverflow.com/a/9256595/14731
 */
 @Documented
 @Nonnull
 @TypeQualifierDefault(
 {
 ElementType.ANNOTATION_TYPE,
 ElementType.CONSTRUCTOR,
 ElementType.FIELD,
 ElementType.LOCAL_VARIABLE,
 ElementType.METHOD,
 ElementType.PACKAGE,
 ElementType.PARAMETER,
 ElementType.TYPE
 })
 @Retention(RetentionPolicy.RUNTIME)
 public @interface NotNullByDefault
 {
 }

2.将批注添加到每个软件包: package-info.java


@NotNullByDefault
package com.example.foo;

更新: 2012年12月12日 JSR 305 列表被列为"休眠"。 根据文档:

JSR"休眠"的执行委员会投票,或已达到其自然寿命的终结。

它看起来像 JSR 308 使它变成jdk 8虽然jsr没有定义 @NotNull, 随行 Checkers Framework 。 在撰写本文时,Maven 插件无法使用,原因是 Bug: http://code.google.com checker-framework/issues/detail?id=183

Eclipse 也有自己的注解。


**org.eclipse.jdt.annotation.NonNull**

有关详细信息,请参阅 http://wiki.eclipse.org/JDT_Core/Null_Analysis

对于Android项目,你应该使用 android.support.annotation.NonNullandroid.support.annotation.Nullable 这些和其他有用的Android-specific注释在支持库 。中可用。

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

支持库本身也有注解,所以作为支持库的用户,Android Studio 将已经检查你的代码并根据这些注释标记潜在问题。

如果有人只是在寻找IntelliJ类: 你可以从 Maven 仓库获得它们,


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

当在上游( 爪哇 8) 中进行排序时,你也可以定义自己的project-local @NotNull@Nullable 注释。 如果你使用的是 Java SE,这也很有用,其中 javax.validation.constraints在默认情况下不可用。


import java.lang.annotation.*;

/**
 * Designates that a field, return value, argument, or variable is
 * guaranteed to be non-null.
 */
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
@Documented
@Retention(RetentionPolicy.CLASS)
public @interface NotNull {}

/**
 * Designates that a field, return value, argument, or variable may be null.
 */
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
@Documented
@Retention(RetentionPolicy.CLASS)
public @interface Nullable {}

这主要是为了装饰或者future-proofing的目的,因为上面显然没有为这些注解的静态分析添加任何支持。

...