【问题标题】:Why doesn't @NotNull or @Nullable exist in my project?为什么我的项目中不存在@NotNull 或@Nullable?
【发布时间】:2022-01-01 11:51:21
【问题描述】:

我正在使用 IntelliJ 进行编程,并且我正在处理一个 Java 项目,并且我想制作一个注释为 @NotNull 的参数。但 IntelliJ 说它不存在。我检查了所有的 java 文件,但它不在我的项目中。我很困惑,我没有使用maven或gradle,只是默认的Java项目。我不知道发生了什么。

这是一个例子:

package com.company;


    public class Main {
         public static void main(String[] args){
                testF(null);
         }
         public static void testF (@NotNull Integer... numbers){
            for(Integer integer: numbers){
                   System.out.println(integer);
          }
     }
}

说“无法解析符号 NotNul : 10”时出现错误(前面还是 @)

【问题讨论】:

  • @NotNull 不是标准 java API 的一部分,而是Jakarta (jakarta.ee) 的一部分
  • @Turing95 @NotNull 在大约 5 个不同的库中,特别是包括 hibernate,它意味着完全不同的东西(即:“如果创建此表,则添加非空约束”)。 @NonNull 在更多库中。

标签: java intellij-idea annotations


【解决方案1】:

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 解决了这个问题。

【讨论】:

    猜你喜欢
    • 2013-05-17
    • 2014-09-11
    • 1970-01-01
    • 2014-03-23
    • 1970-01-01
    • 2016-12-05
    • 1970-01-01
    • 2018-12-07
    • 2017-11-23
    相关资源
    最近更新 更多