Java 本身不附带这些注释。
相反,这个想法有大约 10 种相互不兼容的观点,其中大多数的工作方式完全不同,并且对 NonNull 的含义、您可以将它放在哪里以及它是如何工作的应用了不同的含义。
哎呀。这是非常不幸的,因为使用注释添加此信息的基本思想大大优于 Optional 等,因为它完全向后兼容并且不会将现有代码降级为过时的低迷,这与 Optional 不同。
所以,找到一个你喜欢的,并把它包含在你的项目中,就像你包含任何第三方依赖一样——通常是通过将它包含在你的 Maven/Gradle/Ant+ivy/etc(你的构建文件的依赖列表)中。
Intellij 对 NonNull 和 Nullable 有自己的看法。这可能是最方便的。它对这些注释含义的想法是劣等的1。 Checker 框架是最好的,eclipse 是第二好,其他所有东西(包括 intellij 的)都排在第三位。最好的方法是在 Checker Framework 中找到,或者几乎同样好,eclipse 对这些注释的看法。但是,我怀疑 intellij 的空值检查系统是否能够完全理解其更高级的附加功能,例如 @PolyNull,因此这种附加的表达能力大部分会被浪费掉。作为奖励,intellij 附带了大量关于主要库中正确的无效注释的数据。
最后一个很重要:最常用的 java 库,包括 java.* 本身,没有这些注释,使用半空注释代码绝对是一个非常令人沮丧的练习;这样做的成本大大超过了收益。唯一真正的解决方案是使用正确的无效信息“修复”您使用的库,但这是一项繁重的工作。幸运的是,intellij 已经为您做了很多。
我希望(eclipse 会这样做),quickfix(mac 上的 CMD+1,非 mac 上的 CTRL+1,至少,如果我对默认键盘快捷键的记忆为我服务,开箱即用)包括“自动将eclipse的无效注释添加到类路径'(或者在你的情况下,当然是intellij的)。如果不知何故没有出现,This page from the intellij docs 准确解释如何将包含无效注释的org.jetbrains.annotations 库添加到您的项目中。事实上,这些文档表明,确实,quickfix 菜单确实为您提供了自动添加此库的选项,以解决您在源代码中的 @NonNull 节点上遇到的错误。
[1] 大多数对 nullity 的注解都极大地限制了自己,因为它只允许在字段、方法(暗示:它返回什么)和参数上进行注解。但是,可以有一个绝对不为空的List 的可能为空的Map 实例,将绝对不为空的String 映射到可能为空的Integer:@NonNull List<@Nullable Map<@NonNull String, @Nullable Integer>>。注释系统能够让您编写它,但前提是您的注释仅针对 TYPE_USE 设置。 checker 框架和 eclipse 的 nullity 注释就是这样工作的;大多数其他人没有,因此表达力较差。 CheckerFramework 更进了一步,让您可以编写“任何一个无效都可以”的概念。就像泛型有 3 种形式(List<Integer>、List<? super Integer> 和 List< extends Integer>)一样,一旦涉及泛型,2 个空值(从不为空,或绝对允许空)已不再足够,您需要更多空值。检查器框架has @PolyNull 将让您链接空值:例如,您可以在 checkerframework 中编写此方法,但您不可能使用 intellij 或 eclipse 的正确类型编写它:
public void duplicateFirstMatch(List<T> elems, Predicate<T> matcher);
这里的想法是:这个方法对列表中的每个元素运行匹配器,并且在匹配时,该元素被添加到列表的末尾。如果T 被认为是'@NonNull',则此方法可以工作(鉴于没有空值,此代码永远不能添加空值,因此它不能违反其元素的非空性),但它只是工作同样,如果T 是@Nullable,当然前提是匹配器也是@Nullable T:现在这段代码可能会将null 添加到列表中,但这没关系。
因此T 既不是Nullable 也不是NonNull,但是签名中提到的T 确实需要匹配它们的nullity。 @PolyNull 解决了这个问题。