首页 文章

我应该使用哪个@NotNull Java注释?

提问于
浏览
796

我在我的代码中注释并列出所有这些内容,读起来很糟糕 . 有什么建议'best'?这是我发现的等效注释列表:

20 回答

  • 17

    不是't sun have their own now? What'这个:
    http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Modules-com.sun/istack/com.sun.istack.internal.htm

    这似乎与我在过去几年中使用的所有Java版本打包在一起 .

    Edit: 如下面的评论所述,您可能不想使用这些 . 在这种情况下,我的投票是针对IntelliJ jetbrains注释!

  • 5

    根据Java 7 features list JSR-308类型注释被推迟到Java 8.甚至没有提到JSR-305注释 .

    在最新的JSR-308草案的_297826中,有一些关于JSR-305状态的信息 . 这包括观察到JSR-305注释似乎被放弃了 . JSR-305页面也将其显示为"inactive" .

    同时,实用的答案是使用最广泛使用的工具支持的注释类型......并准备好在情况发生变化时更改它们 .


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

    但是,如果JSR-308真的看起来像是在Java 8中,那么如果对JSR-305的兴趣恢复,那就不会让我感到惊讶 . AFAIK,JSR-305团队尚未正式放弃他们的工作 . 他们刚刚安静了2年 .

    有趣的是,Bill Pugh(JSR-305的技术主管)是FindBugs背后的人之一 .

  • 3

    对于Android项目,您应该使用 android.support.annotation.NonNullandroid.support.annotation.Nullable . 这些和其他有用的Android特定注释可在Support Library中找到 .

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

    支持库本身也使用这些注释进行了注释,因此作为支持库的用户,Android Studio已经检查了您的代码并根据这些注释标记了潜在的问题 .

  • 2

    如果你在某种程度上与Eclipse有关(编辑:在撰写本文时,不再是),它有自己的注释 . 它包含在Eclipse 3.8(Juno)中,但默认情况下禁用 .

    您可以在首选项> Java>编译器>错误/警告>空分析(底部的可折叠部分)中启用它 .

    选中“启用基于注释的空分析”

    http://wiki.eclipse.org/JDT_Core/Null_Analysis#Usage有关于设置的建议 . 但是,如果您的工作区中有外部项目(如facebook SDK),它们可能无法满足这些建议,您可能不希望在每次SDK更新时修复它们;-)

    我用:

    • 空指针访问:错误

    • 违反空指定:错误(链接到#1点)

    • 潜在的空指针访问:警告(否则facebook SDK会有警告)

    • 空注释与空推理之间的冲突:警告(链接到第3点)

  • 17

    在Java 8中还有另一种方法可以做到这一点 . 我正在做两件事来完成我需要的东西:

    • 通过使用 java.util.Optional 包装可空字段,使可空字段显式化

    • 使用 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 是不好的做法,这里有利弊的好讨论Why should Java 8's Optional not be used in arguments

  • 1

    IntelliJ的一个好处是你不需要使用他们的注释 . 你可以自己编写,也可以使用其他任何你喜欢的工具 . 你甚至不限于一种类型 . 如果您使用两个使用不同@NotNull注释的库,则可以告诉IntelliJ使用它们 . 要执行此操作,请转到“配置检查”,单击“常量条件和例外”检查,然后单击“配置检查”按钮 . 我尽可能使用Nullness Checker,所以我设置IntelliJ来使用这些注释,但是你可以使用你想要的任何其他工具 . (我对其他工具没有意见,因为我多年来一直在使用IntelliJ的检查,我很喜欢它们 . )

  • 12

    只是指出Java Validation API( javax.validation.constraints.* )没有附带 @Nullable 注释,这在静态分析中非常有 Value 上下文 . 它对运行时bean验证有意义,因为这是Java中任何非原始字段的默认值(即,无需验证/强制执行) . 出于上述目的,应该考虑替代方案 .

  • 51

    我非常喜欢Checker Framework,它是类型注释(JSR-308)的实现,用于实现缺陷检查器,如nullness checker . 我对此实施感到满意 .

    我不是提供该软件的团体的附属机构,但我是粉丝 .

    我喜欢这个系统的四件事:

    • 它有nullness(@Nullable)的缺陷检查器,但也有immutabilityinterning(以及其他)的缺陷检查器 . 我使用了第一个(nullness)而我尝试了第三个,但是我还没有确信其他跳棋的一般用处,但很高兴知道框架本身就是一个实现多样化的系统附加注释和检查器 .

    • default setting for nullness checking效果很好:非本地人除外(NNEL) . 基本上这意味着默认情况下,检查器会处理除局部变量之外的每个(实例变量,方法参数,泛型类型等),就像默认情况下它们具有@NonNull类型一样 . 根据文件:

    NNEL默认值导致代码中显式注释的数量最少 .

    如果NNEL不适合您,您可以为类或方法设置不同的默认值 .

    • 此框架允许您通过在注释中包含注释来使用 without creating a dependency on the framework :例如 /*@Nullable*/ . 这很好,因为您可以注释和检查库或共享代码,但仍然能够在另一个没有习惯使用它的项目中使用该库/共享编码,即使我倾向于在所有项目上启用Checker Framework我的项目现在 .

    • 框架有一种方法可以使用尚未使用存根文件注释null的annotate APIs .

  • 11

    如果有人只是在寻找IntelliJ类:你可以从maven存储库获取它们

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

    自从Oracle decided not to standardize @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注释都有这条线

    public @interface NonNull {}
    

    除了

    • org.jetbrains.annotations将其称为@NotNull,并且具有简单的实现

    • javax.annotation具有更长的实现

    • javax.validation.constraints也称它为@NotNull并具有实现

    @Nullable注释都有这一行

    public @interface 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)) .

    this SO answer中所述,运行时注释的影响小于人们可能认为的影响,但除了编译时间之外,它们还有使工具能够进行运行时检查的好处 .

    另一个重要的区别是在代码中可以使用注释 . 有两种不同的方法 . 一些包使用JLS 9.6.4.1样式上下文 . 下表给出了概述:

    FIELD   METHOD  PARAMETER LOCAL_VARIABLE 
    android.support.annotation      X       X       X   
    edu.umd.cs.findbugs.annotations X       X       X         X
    org.jetbrains.annotation        X       X       X         X
    lombok                          X       X       X         X
    javax.validation.constraints    X       X       X
    

    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字段并对资格进行了规范化 .

    package android.support.annotation;
    @Retention(CLASS)
    @Target({FIELD, METHOD, PARAMETER})
    public @interface NonNull {}
    

    package edu.umd.cs.findbugs.annotations;
    @Retention(CLASS)
    @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
    public @interface NonNull {}
    

    package org.eclipse.jdt.annotation;
    @Retention(CLASS)
    @Target({ TYPE_USE })
    public @interface NonNull {}
    

    package org.jetbrains.annotations;
    @Retention(CLASS)
    @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
    public @interface NotNull {String value() default "";}
    

    package javax.annotation;
    @TypeQualifier
    @Retention(RUNTIME)
    public @interface Nonnull {
        When when() default When.ALWAYS;
        static class Checker implements TypeQualifierValidator<Nonnull> {
            public When forConstantValue(Nonnull qualifierqualifierArgument,
                    Object value) {
                if (value == null)
                    return When.NEVER;
                return When.ALWAYS;
            }
        }
    }
    

    package org.checkerframework.checker.nullness.qual;
    @Retention(RUNTIME)
    @Target({TYPE_USE, TYPE_PARAMETER})
    @SubtypeOf(MonotonicNonNull.class)
    @ImplicitFor(
        types = {
            TypeKind.PACKAGE,
            TypeKind.INT,
            TypeKind.BOOLEAN,
            TypeKind.CHAR,
            TypeKind.DOUBLE,
            TypeKind.FLOAT,
            TypeKind.LONG,
            TypeKind.SHORT,
            TypeKind.BYTE
        },
        literals = {LiteralKind.STRING}
    )
    @DefaultQualifierInHierarchy
    @DefaultFor({TypeUseLocation.EXCEPTION_PARAMETER})
    @DefaultInUncheckedCodeFor({TypeUseLocation.PARAMETER, TypeUseLocation.LOWER_BOUND})
    public @interface NonNull {}
    

    为了完整性,这里是@Nullable实现:

    package android.support.annotation;
    @Retention(CLASS)
    @Target({METHOD, PARAMETER, FIELD})
    public @interface Nullable {}
    

    package edu.umd.cs.findbugs.annotations;
    @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
    @Retention(CLASS)
    public @interface Nullable {}
    

    package org.eclipse.jdt.annotation;
    @Retention(CLASS)
    @Target({ TYPE_USE })
    public @interface Nullable {}
    

    package org.jetbrains.annotations;
    @Retention(CLASS)
    @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
    public @interface Nullable {String value() default "";}
    

    package javax.annotation;
    @TypeQualifierNickname
    @Nonnull(when = When.UNKNOWN)
    @Retention(RUNTIME)
    public @interface Nullable {}
    

    package org.checkerframework.checker.nullness.qual;
    @Retention(RUNTIME)
    @Target({TYPE_USE, TYPE_PARAMETER})
    @SubtypeOf({})
    @ImplicitFor(
        literals = {LiteralKind.NULL},
        typeNames = {java.lang.Void.class}
    )
    @DefaultInUncheckedCodeFor({TypeUseLocation.RETURN, TypeUseLocation.UPPER_BOUND})
    public @interface Nullable {}
    

    以下两个包没有@Nullable,所以我单独列出它们lombok有一个非常无聊的@NonNull . 在javax.validation.constraints中,@ NonNull实际上是一个@NotNull,它有一个很长的实现 .

    package lombok;
    @Retention(CLASS)
    @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
    public @interface NonNull {}
    

    package javax.validation.constraints;
    @Retention(RUNTIME)
    @Target({ FIELD, METHOD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
    @Constraint(validatedBy = {})
    public @interface NotNull {
        String message() default "{javax.validation.constraints.NotNull.message}";
        Class<?>[] groups() default { };
        Class<? extends Payload>[] payload() default {};
        @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
        @Retention(RUNTIME)
        @Documented
        @interface List {
            NotNull[] value();
        }
    }
    

    支持

    从我的经验来看,javax.annotation至少得到Eclipse和Checker Framework的支持 .

    摘要

    我理想的注释是带有Checker Framework实现的java.annotation语法 .

    如果您不打算使用Checker Framework,那么 javax.annotationJSR-305)仍然是您最好的选择 .

    如果您愿意购买Checker Framework,只需使用他们的org.checkerframework.checker.nullness.qual .


    来源

    来自android-5.1.1_r1.jar的

    • android.support.annotation
      来自findbugs-annotations-1.0.0.jar的
    • edu.umd.cs.findbugs.annotations
      来自org.eclipse.jdt.annotation_2.1.0.v20160418-1457.jar的
    • org.eclipse.jdt.annotation
      来自jetbrains-annotations-13.0.jar的
    • org.jetbrains.annotations
      来自gwt-dev-2.5.1-sources.jar的
    • javax.annotation
      来自checker-framework-2.1.9.zip的
    • org.checkerframework.checker.nullness.qual
      来自lombok的
    • lombok提交f6da35e4c4f3305ecd1b415e2ab1b9ef8a9120b4
      来自validation-api-1.0.0.GA-sources.jar的
    • javax.validation.constraints
  • 32

    不幸的是, JSR 308 不会在这里添加比本项目本地Not Null建议更多的值

    Java 8 不会带有单个默认注释或其自己的 Checker 框架 . 与Find-bugs或 JSR 305 类似,这个JSR很少由一小部分学术团队维护 .

    它背后没有任何商业力量,因此 JSR 308 (早期草案在 JCP )现在发布,而 Java 8 应该在不到6个月内发货:-O类似于 310 顺便说一句 . 但与 308 Oracle 不同的是,现在已经掌握了它的创始人,以尽量减少它对Java平台造成的伤害 .

    Checker FrameworkJSR 308 背后的每个项目,供应商和学术类都将创建自己的专有检查器注释 .

    使源代码在未来几年内不兼容,直到可以找到一些流行的妥协,并可能添加到 Java 910 ,或者通过 Apache CommonsGoogle Guava ;-)等框架

  • 3

    如果您使用Spring Framework构建应用程序,我建议使用 javax.validation.constraints.NotNull 来自Beans Validation打包在以下依赖项中:

    <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.1.0.Final</version>
        </dependency>
    

    这个注释的主要优点是Spring提供了对使用 javax.validation.constraints.NotNull 注释的方法参数和类字段的支持 . 您需要做的就是启用支持:

    • 为bean验证和jar提供api jar,实现了jsr-303 / jsr-349注释的验证器(它附带了Hibernate Validator 5.x依赖):
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>1.1.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>5.4.1.Final</version>
    </dependency>
    
    • 为Spring的上下文提供MethodValidationPostProcessor
    @Configuration
      @ValidationConfig
      public class ValidationConfig implements MyService {
    
            @Bean
            public MethodValidationPostProcessor providePostProcessor() {
                  return new MethodValidationPostProcessor()
            }
      }
    

    例:

    @Service
    @Validated
    public class MyServiceImpl implements MyService {
    
      @Override
      public Something doSomething(@NotNull String myParameter) {
            // No need to do something like assert myParameter != null  
      }
    }
    

    当您尝试调用方法doSomething并传递null作为参数值时,spring(通过HibernateValidator)将抛出 ConstraintViolationException . 这里不需要手工操作 .

    您还可以验证返回值 .

    javax.validation.constraints.NotNull 为Beans Validation Framework提供的另一个重要好处是,目前它仍在开发中,并且计划为新版本2.0提供新功能 .

    @Nullable 怎么样? Beans Validation 1.1中没有类似的东西 . 好吧,我可以说如果你决定使用 @NotNull 而不是 @NonNull 注释的所有内容实际上都是"nullable",那么 @Nullable 注释就没用了 .

  • 2

    JSR305和FindBugs由同一个人创作 . 两者都维护得很差,但它们是标准的,并得到所有主要IDE的支持 . 好消息是它们按原样运行良好 .

    以下是默认情况下如何将@Nonnull应用于所有类,方法和字段 . 见https://stackoverflow.com/a/13319541/14731https://stackoverflow.com/a/9256595/14731

    • 定义 @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 https://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;
    

    UPDATE :截至2012年12月12日JSR 305列为"Dormant" . 根据文件:

    一个被执行委员会评为“休眠”的JSR,或者已经达到其自然寿命终结的JSR .

    它看起来像JSR 308 is 进入JDK 8,虽然JSR没有定义@NotNull,但伴随的 Checkers Framework 确实如此 . 在撰写本文时,由于此错误,Maven插件无法使用:https://github.com/typetools/checker-framework/issues/183

  • 1

    Eclipse也有自己的注释 .

    org.eclipse.jdt.annotation.NonNull
    

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

  • 25

    区分静态分析和运行时分析 . 对内部事物使用静态分析,对代码的公共边界使用运行时分析 .

    对于不应为null的事物:

    • 运行时检查:使用“if(x == null)...”(零依赖)或@ javax.validation.NotNull(使用bean验证)或@ lombok.NonNull(简单和简单)或guavas Preconditions.checkNotNull( . ..)

    • 对于方法返回类型,仅使用Optional(仅限) . Java8或Guava .

    • 静态检查:使用@NonNull注释

    • 在适合的地方,在类或包级别使用@ ... NonnullByDefault注释 . 自己创建这些注释(示例很容易找到) .

    • 否则,使用@ ... CheckForNull方法返回以避免NPE

    这应该是最好的结果:IDE中的警告,Findbugs和checkerframework的错误,有意义的运行时异常 .

    不要指望静态检查是成熟的,它们的命名不是标准化的,不同的库和IDE会以不同的方式对待它们,忽略它们 . JSR305 javax.annotations . *类看起来像标准,但它们不是,它们会导致Java9的拆分包 .

    一些说明解释:

    • Findbugs / spotbugs / jsr305注释包javax.validation . *与Java9中的其他模块发生冲突,也可能违反Oracle许可

    • Spotbugs注释仍然依赖于编译时的jsr305 / findbugs注释(在编写https://github.com/spotbugs/spotbugs/issues/421时)

    • jetbrains @NotNull名称与@ javax.validation.NotNull冲突 .
      用于静态检查的

    • jetbrains,eclipse或checkersframework注释比javax.annotations更有优势,它们不会与Java9及更高版本中的其他模块冲突

    • @ javax.annotations.Nullable并不意味着Findbugs / Spotbugs你(或你的IDE)认为它意味着什么 . Findbugs会忽略它(在成员身上) . 伤心,但是真的(https://sourceforge.net/p/findbugs/bugs/1181

    • 对于IDE外部的静态检查,存在2个免费工具:Spotbugs(以前称为Findbugs)和checkersframework .

    • Eclipse库有@NonNullByDefault,jsr305只有@ParametersAreNonnullByDefault . 这些仅仅是将基础注释应用于包(或类)中的所有东西的便利包装器,您可以轻松创建自己的 . 这可以在包装上使用 . 这可能与生成的代码(例如lombok)冲突 .

    • Eclipse jdt注释不适用于静态方法返回和其他一些情况

    • 对于与其他人共享的库,应避免使用lombok作为导出的依赖项,传递依赖性越小越好

    • 使用Bean验证框架功能强大,但需要很高的开销,因此过度杀戮只是为了避免手动空值检查 .

    • 对字段和方法参数使用Optional是有争议的(您可以轻松找到有关它的文章)

    • Android null注释是Android支持库的一部分,它们带有很多其他类,并且不能与其他注释/工具很好地配合使用

    在Java9之前,这是我的建议:

    // file: package-info.java
    @javax.annotation.ParametersAreNonnullByDefault
    package example;
    
    
    // file: PublicApi
    package example;
    
    public class PublicApi {
    
        /**
         * @param firstname MUST NOT be null
         * @param lastname MUST NOT be null
         */
        public Person createPerson(
                // Spotbugs ignores the param annotations, but IDEs will show problems
                @Nullable String firstname, // Users  might send null
                @Nullable String lastname // Users might send null
                ) {
            if (firstname == null) throw new IllagalArgumentException(...);
            if (lastname == null) throw new IllagalArgumentException(...);
            return doCreatePerson(fistname, lastname, nickname);
        }
    
        @NonNull // Spotbugs checks that method cannot return null
        private Person doCreatePerson(
                 String firstname, // Spotbugs checks null cannot be passed, because package has ParametersAreNonnullByDefault
                 String lastname,
                 @Nullable String nickname // tell Spotbugs null is ok
                 ) {
             return new Person(firstname, lastname, nickname);
        }
    
        @CheckForNull // Do not use @Nullable here, Spotbugs will ignore it, though IDEs respect it
        private Person getNickname(
             String firstname,
             String lastname) {
             return NICKNAMES.get(firstname + ':' + lastname);
        }
    }
    

    请注意,当取消引用可以为null的方法参数时(在撰写本文时,Spotbugs版本为3.1),无法使Spotbugs发出警告 . 也许checkerframework可以做到这一点 .

  • 7

    另一个选项是ANTLR 4提供的注释 . 在Pull Request #434之后,包含 @NotNull@Nullable 注释的工件包括一个注释处理器,如果其中一个属性被误用,它会产生编译时错误和/或警告(例如,如果两者都被误用)应用于同一项目,或者如果 @Nullable 应用于具有基本类型的项目) . 注释处理器在软件开发过程中提供额外的保证,即通过应用这些注释所传达的信息是准确的,包括在方法继承的情况下 .

  • 6

    Android

    这个答案是Android特有的 . Android有一个名为 support-annotations 的支持包 . 这提供dozensAndroid specific注释,并提供common ones,如 NonNullNullable 等 .

    要添加support-annotations包,请在build.gradle中添加以下依赖项:

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

    然后使用:

    import android.support.annotation.NonNull;
    
    void foobar(@NonNull Foo bar) {}
    
  • 88

    我使用IntelliJ,因为我主要关注IntelliJ标记可能产生NPE的东西 . 我同意在JDK中没有标准注释令人沮丧 . 有关添加它的讨论,它可能会成为Java 7.在这种情况下,还有一个可供选择!

  • 4

    在等待上游排序(Java 8?)时,您还可以定义自己的项目本地 @NotNull@Nullable 注释 . 如果您正在使用Java SE,这也很有用,默认情况下为 javax.validation.constraints isn't available .

    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 {}
    

    这无疑主要是用于装饰或面向未来的目的,因为上面显然本身并没有为这些注释的静态分析添加任何支持 .

  • 7

    如果您正在处理一个大项目,那么最好创建 your own @Nullable 和/或 @NotNull 注释 .

    例如:

    @java.lang.annotation.Documented
    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)
    @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD,
                                  java.lang.annotation.ElementType.METHOD,    
                                  java.lang.annotation.ElementType.PARAMETER,
                                  java.lang.annotation.ElementType.LOCAL_VARIABLE})
    public @interface Nullable 
    {
    }
    

    如果使用正确的retention policy,则注释 won't be available at runtime . 从这个角度来看,它只是一个 internal 事物 .

    尽管这不是一门严格的科学,但我认为使用 internal 类是最有意义的 .

    • 这是内部事情 . (无功能或技术影响)

    • 有许多用法 .

    • IDE就像IntelliJ支持自定义 @Nullable / @NotNull 注释 .

    • 大多数框架也喜欢使用自己的内部版本 .

    其他问题(见评论):

    How to configure this in IntelliJ ?

    单击IntelliJ状态栏右下角的“警务人员” . 然后单击弹出窗口中的“配置检查” . 下一个 ...

相关问题