我在我的代码中注释并列出所有这些内容,读起来很糟糕 . 有什么建议'best'?这是我发现的等效注释列表:
-
javax.validation.constraints.NotNull
为运行时验证而不是静态分析而创建 .
documentation -
edu.umd.cs.findbugs.annotations.NonNull
由Findbugs静态分析使用,因此声纳(现在Sonarqube)
documentation -
javax.annotation.Nonnull
这也适用于Findbugs,但JSR-305无效 . (参见:What is the status of JSR 305?)source -
org.jetbrains.annotations.NotNull
由IntelliJ IDEA IDE用于静态分析 .
documentation -
lombok.NonNull
用于控制Project Lombok中的代码生成 .
占位符注释,因为没有标准 .
source,documentation -
android.support.annotation.NonNull
Android中提供的标记注释,由support-annotations包提供
documentation -
org.eclipse.jdt.annotation.NonNull
由Eclipse用于静态代码分析
documentation
20 回答
不是'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注释!
根据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背后的人之一 .
对于Android项目,您应该使用
android.support.annotation.NonNull
和android.support.annotation.Nullable
. 这些和其他有用的Android特定注释可在Support Library中找到 .来自http://tools.android.com/tech-docs/support-annotations:
如果你在某种程度上与Eclipse有关(编辑:在撰写本文时,不再是),它有自己的注释 . 它包含在Eclipse 3.8(Juno)中,但默认情况下禁用 .
您可以在首选项> Java>编译器>错误/警告>空分析(底部的可折叠部分)中启用它 .
选中“启用基于注释的空分析”
http://wiki.eclipse.org/JDT_Core/Null_Analysis#Usage有关于设置的建议 . 但是,如果您的工作区中有外部项目(如facebook SDK),它们可能无法满足这些建议,您可能不希望在每次SDK更新时修复它们;-)
我用:
空指针访问:错误
违反空指定:错误(链接到#1点)
潜在的空指针访问:警告(否则facebook SDK会有警告)
空注释与空推理之间的冲突:警告(链接到第3点)
在Java 8中还有另一种方法可以做到这一点 . 我正在做两件事来完成我需要的东西:
通过使用
java.util.Optional
包装可空字段,使可空字段显式化使用
java.util.Objects.requireNonNull
检查构造时所有非可空字段是否为空例:
所以我的问题是,我们甚至需要在使用java 8时进行注释吗?
编辑:后来我发现有些人认为在参数中使用
Optional
是不好的做法,这里有利弊的好讨论Why should Java 8's Optional not be used in argumentsIntelliJ的一个好处是你不需要使用他们的注释 . 你可以自己编写,也可以使用其他任何你喜欢的工具 . 你甚至不限于一种类型 . 如果您使用两个使用不同@NotNull注释的库,则可以告诉IntelliJ使用它们 . 要执行此操作,请转到“配置检查”,单击“常量条件和例外”检查,然后单击“配置检查”按钮 . 我尽可能使用Nullness Checker,所以我设置IntelliJ来使用这些注释,但是你可以使用你想要的任何其他工具 . (我对其他工具没有意见,因为我多年来一直在使用IntelliJ的检查,我很喜欢它们 . )
只是指出Java Validation API(
javax.validation.constraints.*
)没有附带@Nullable
注释,这在静态分析中非常有 Value 上下文 . 它对运行时bean验证有意义,因为这是Java中任何非原始字段的默认值(即,无需验证/强制执行) . 出于上述目的,应该考虑替代方案 .我非常喜欢Checker Framework,它是类型注释(JSR-308)的实现,用于实现缺陷检查器,如nullness checker . 我对此实施感到满意 .
我不是提供该软件的团体的附属机构,但我是粉丝 .
我喜欢这个系统的四件事:
它有nullness(@Nullable)的缺陷检查器,但也有immutability和interning(以及其他)的缺陷检查器 . 我使用了第一个(nullness)而我尝试了第三个,但是我还没有确信其他跳棋的一般用处,但很高兴知道框架本身就是一个实现多样化的系统附加注释和检查器 .
default setting for nullness checking效果很好:非本地人除外(NNEL) . 基本上这意味着默认情况下,检查器会处理除局部变量之外的每个(实例变量,方法参数,泛型类型等),就像默认情况下它们具有@NonNull类型一样 . 根据文件:
如果NNEL不适合您,您可以为类或方法设置不同的默认值 .
此框架允许您通过在注释中包含注释来使用 without creating a dependency on the framework :例如
/*@Nullable*/
. 这很好,因为您可以注释和检查库或共享代码,但仍然能够在另一个没有习惯使用它的项目中使用该库/共享编码,即使我倾向于在所有项目上启用Checker Framework我的项目现在 .框架有一种方法可以使用尚未使用存根文件注释null的annotate APIs .
如果有人只是在寻找IntelliJ类:你可以从maven存储库获取它们
自从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注释都有这条线
除了
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)) .
如this SO answer中所述,运行时注释的影响小于人们可能认为的影响,但除了编译时间之外,它们还有使工具能够进行运行时检查的好处 .
另一个重要的区别是在代码中可以使用注释 . 有两种不同的方法 . 一些包使用JLS 9.6.4.1样式上下文 . 下表给出了概述:
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,所以我单独列出它们lombok有一个非常无聊的@NonNull . 在javax.validation.constraints中,@ NonNull实际上是一个@NotNull,它有一个很长的实现 .
支持
从我的经验来看,javax.annotation至少得到Eclipse和Checker Framework的支持 .
摘要
我理想的注释是带有Checker Framework实现的java.annotation语法 .
如果您不打算使用Checker Framework,那么 javax.annotation (JSR-305)仍然是您最好的选择 .
如果您愿意购买Checker Framework,只需使用他们的org.checkerframework.checker.nullness.qual .
来源
来自android-5.1.1_r1.jar的
来自findbugs-annotations-1.0.0.jar的
来自org.eclipse.jdt.annotation_2.1.0.v20160418-1457.jar的
来自jetbrains-annotations-13.0.jar的
来自gwt-dev-2.5.1-sources.jar的
来自checker-framework-2.1.9.zip的
来自lombok的
来自validation-api-1.0.0.GA-sources.jar的
不幸的是,
JSR 308
不会在这里添加比本项目本地Not Null建议更多的值Java 8
不会带有单个默认注释或其自己的Checker
框架 . 与Find-bugs或JSR 305
类似,这个JSR很少由一小部分学术团队维护 .它背后没有任何商业力量,因此
JSR 308
(早期草案在JCP
)现在发布,而Java 8
应该在不到6个月内发货:-O类似于310
顺便说一句 . 但与308 Oracle
不同的是,现在已经掌握了它的创始人,以尽量减少它对Java平台造成的伤害 .像
Checker Framework
和JSR 308
背后的每个项目,供应商和学术类都将创建自己的专有检查器注释 .使源代码在未来几年内不兼容,直到可以找到一些流行的妥协,并可能添加到
Java 9
或10
,或者通过Apache Commons
或Google Guava
;-)等框架如果您使用Spring Framework构建应用程序,我建议使用
javax.validation.constraints.NotNull
来自Beans Validation打包在以下依赖项中:这个注释的主要优点是Spring提供了对使用
javax.validation.constraints.NotNull
注释的方法参数和类字段的支持 . 您需要做的就是启用支持:例:
当您尝试调用方法doSomething并传递null作为参数值时,spring(通过HibernateValidator)将抛出
ConstraintViolationException
. 这里不需要手工操作 .您还可以验证返回值 .
javax.validation.constraints.NotNull
为Beans Validation Framework提供的另一个重要好处是,目前它仍在开发中,并且计划为新版本2.0提供新功能 .@Nullable
怎么样? Beans Validation 1.1中没有类似的东西 . 好吧,我可以说如果你决定使用@NotNull
而不是@NonNull
注释的所有内容实际上都是"nullable",那么@Nullable
注释就没用了 .JSR305和FindBugs由同一个人创作 . 两者都维护得很差,但它们是标准的,并得到所有主要IDE的支持 . 好消息是它们按原样运行良好 .
以下是默认情况下如何将@Nonnull应用于所有类,方法和字段 . 见https://stackoverflow.com/a/13319541/14731和https://stackoverflow.com/a/9256595/14731
@NotNullByDefault
2.将注释添加到每个包:
package-info.java
UPDATE :截至2012年12月12日JSR 305列为"Dormant" . 根据文件:
它看起来像JSR 308 is 进入JDK 8,虽然JSR没有定义@NotNull,但伴随的
Checkers Framework
确实如此 . 在撰写本文时,由于此错误,Maven插件无法使用:https://github.com/typetools/checker-framework/issues/183Eclipse也有自己的注释 .
有关详细信息,请参阅http://wiki.eclipse.org/JDT_Core/Null_Analysis .
区分静态分析和运行时分析 . 对内部事物使用静态分析,对代码的公共边界使用运行时分析 .
对于不应为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之前,这是我的建议:
请注意,当取消引用可以为null的方法参数时(在撰写本文时,Spotbugs版本为3.1),无法使Spotbugs发出警告 . 也许checkerframework可以做到这一点 .
另一个选项是ANTLR 4提供的注释 . 在Pull Request #434之后,包含
@NotNull
和@Nullable
注释的工件包括一个注释处理器,如果其中一个属性被误用,它会产生编译时错误和/或警告(例如,如果两者都被误用)应用于同一项目,或者如果@Nullable
应用于具有基本类型的项目) . 注释处理器在软件开发过程中提供额外的保证,即通过应用这些注释所传达的信息是准确的,包括在方法继承的情况下 .Android
这个答案是Android特有的 . Android有一个名为
support-annotations
的支持包 . 这提供dozens的Android specific注释,并提供common ones,如NonNull
,Nullable
等 .要添加support-annotations包,请在build.gradle中添加以下依赖项:
然后使用:
我使用IntelliJ,因为我主要关注IntelliJ标记可能产生NPE的东西 . 我同意在JDK中没有标准注释令人沮丧 . 有关添加它的讨论,它可能会成为Java 7.在这种情况下,还有一个可供选择!
在等待上游排序(Java 8?)时,您还可以定义自己的项目本地
@NotNull
和@Nullable
注释 . 如果您正在使用Java SE,这也很有用,默认情况下为javax.validation.constraints
isn't available .这无疑主要是用于装饰或面向未来的目的,因为上面显然本身并没有为这些注释的静态分析添加任何支持 .
如果您正在处理一个大项目,那么最好创建 your own
@Nullable
和/或@NotNull
注释 .例如:
如果使用正确的retention policy,则注释 won't be available at runtime . 从这个角度来看,它只是一个 internal 事物 .
尽管这不是一门严格的科学,但我认为使用 internal 类是最有意义的 .
这是内部事情 . (无功能或技术影响)
有许多用法 .
IDE就像IntelliJ支持自定义
@Nullable
/@NotNull
注释 .大多数框架也喜欢使用自己的内部版本 .
其他问题(见评论):
How to configure this in IntelliJ ?