Java 我应该同时使用@NotNull和@NonNull吗?

Java 我应该同时使用@NotNull和@NonNull吗?,java,spring-boot,lombok,Java,Spring Boot,Lombok,我使用javax.validation.constraints.NotNull检查hiberbate空字段。现在我使用lombok简化构造函数代码,但我需要使用@NonNull注释使字段包含在所需的字段构造函数中。我应该同时使用它们吗?对于非空注释的作用,至少有4个完全不同的含义。大多数注释仅暗示这些不同的事物中的一种。因此,是的,应用多个这样的注释是有意义的。不幸的是,这些注释的实际含义相当混乱,因为根据我的经验,几乎没有开发人员考虑过它们的含义不同这一事实;事实上,我遇到的大多数开发人员都完

我使用javax.validation.constraints.NotNull检查hiberbate空字段。现在我使用lombok简化构造函数代码,但我需要使用@NonNull注释使字段包含在所需的字段构造函数中。我应该同时使用它们吗?

对于非空注释的作用,至少有4个完全不同的含义。大多数注释仅暗示这些不同的事物中的一种。因此,是的,应用多个这样的注释是有意义的。不幸的是,这些注释的实际含义相当混乱,因为根据我的经验,几乎没有开发人员考虑过它们的含义不同这一事实;事实上,我遇到的大多数开发人员都完全没有意识到空值注释是极其复杂和模糊的

类型系统解释('cannot be!') 这种解释是一种类型断言,它试图与
字符串x中的
字符串
一样强大
is:对于
x
变量,引用一个不是字符串的对象是不可能的,因为这是不可能的,自然,检查这一点是完全无用的。考虑到这个声明,像
stringz=(String)x
这样的东西是非常无用的,实际上它是一个编译器警告

这样的注释也是如此。例如checkerframework、eclipse和intellij的:
org.checkerframeworkchecker.nullness.qual.NonNull
org.jetbrains.annotations.NotNull
和eclipse的
org.eclipse.jdt.annotation.NonNull
都主要暗示了这一含义(尽管intellij one适用于参数和方法,而checkerframework和eclipse是类型_-use注释。我告诉过你这很复杂:P)

这些注释暗示“不能”,用于写时检查。出于同样的原因,在编写代码时,甚至在保存文件之前,编写
String x=5;
是一个立即命令,在IDE中使用红色波浪下划线,比如说编写
someMethod(map.get(key))也是如此
,其中someMethod的参数用其中一个
非null
注释进行注释。与其说是“你不应该”,不如说是“你不能那样做;我甚至不会让你这样做”

当然,javac编译器实际上并不是这样工作的,它是试图使它看起来像这样的IDE和工具。就像你永远不会把一个字符串类型变量转换成字符串一样,实际上你不认为这些无效注释意味着你应该检查。你不需要再检查

当然,这很复杂:围绕java编译器是否会阻止您破坏这些非空注释的含义这一事实跳舞……一些工具(如kotlinc)无论如何,将注入显式的Null检查。有点像泛型可以导致JavaC在您从未编写过明确的CAST的地方注入一些类型检查,以解决泛型是一个编译时螺栓以保持向后兼容性的事实。这个想法是考虑这些不应该考虑的实现细节。 争议裁决委员会的解释 当hibernate使用类作为模板来生成
CREATE TABLE
SQL语句时,能够使用注释来设置约束和规则等是非常有用的。出于同样的原因,您可能希望将字段标记为:“当将其转换为SQL列时,请告诉DB引擎对此设置唯一索引”,您可能希望将其标记为:“当将其转换为SQL列时,请告诉DB引擎对其设置非null约束”

这与类型系统解释的关系就像guns和Grammas一样:您可以拥有表示DB中的行的对象,但由于始终打破约束而无法成功保存;例如,任何自动计数的unid字段通常为0,并且不会这样保存(DB引擎将该0升级为“nevermind that;插入时不插入该值,并让DB引擎的序列填入该数字)。这就是问题所在:它实际上对java没有任何意义;SQL引擎将负责指示插入/更新由于失败的约束而失败。当然,为了保存到DB的往返,并且因为这不允许是简单的,大多数DB框架都将进行空值检查,正如您所说的
.save()的等价物
.store()
。但这只是DB约束的快捷方式

验证解释 有时java中的对象表示外部事物。例如DB行(与前面的意思有些重叠),或者说,用户提交的web表单。这些对象应该准确地表示它所表示的实际外部事物的实际状态。缺点和无效的gobbledygook等等

通常你有一个框架可以让你验证这些。这就是验证非空意味着:这个字段可以是空的,如果你试图将它设置为空,就不会发生异常(因此,它们可以是空的)。但是,只要这个字段保持空,如果你问我对象是否有效,答案是:否

龙目解释 不幸的是,lombok在某种程度上搅乱了局面。就像所有其他框架一样。lombok的
@NonNull
的意思取决于它显示的位置。如果是参数,它的意思是:lombok,请在方法的第一行生成显式nullcheck,除非我自己已经编写了它

字段,这意味着:“为了<代码> @ RealDrgsSu构师,考虑这个字段;Null检查它(在生成的构造函数中抛出一个异常)。同时,复制相关的NultualEng注,因此,如果为这个字段做了一个SETUTER……在NULLCHECK里面添加。 你的具体情况 鉴于无效注释意味着