这很复杂,因为 java 社区以不同的方式处理 null,而“非 null”意味着不同的东西:例如,在 DB 模型类中,它可能意味着:如果您使用 DB 框架生成的 CREATE TABLE 语句要求它为您制作表应该在 SQL 中添加一个 NOT NULL 约束。但是,由于 POJO 也应该能够表示半构建的行(例如,表示数据库中的 unid 列的 unid 字段包含null,因为重点是让数据库使用它的自动序列来填充它,直到你save()它才会发生,因此java端该字段可以并且通常是 null!
因此,lombok 的 NonNull 支持有 4 个方面非常不同:
@RequiredArgsConstructor 和 @AllArgsConstructor,以及暗示其中之一的所有 lombok 功能(@Builder、@Data 和 @Value)。
Lombok 处理 final 或 具有某种 NonNull 注释的任何字段,它明确识别为暗示在该字段为空的情况下甚至不应该存在任何对象(尤其是不包括 JPA 的 NotNull!),并且可以在 lombok.config 中进行配置,但 lombok 附带了一组已知的开箱即用的注释,作为“必需”。
“必填”字段具有以下属性:
-
@RequiredArgsConstructor 会为它做一个参数。
-
@RequiredArgsConstructor 和@AllArgsConstructor 创建的构造函数将使用在 lombok.config 中配置的 nullcheck 机制对这些字段进行 null 检查。默认为:if (x == null) throw new NullPointerException("x");。
@NoArgsConstructor
这个是不同的。 NoArgsConstructor 不添加空检查。这完全没有意义:如果 lombok 应该添加它们,那么这意味着唯一正确的答案是 lombok 为您制作了这个构造函数:
public YourType() {
throw new NullPointerException("NameOfFirstFieldMarkedNonNull");
}
这似乎是一个毫无意义的练习。
因此,相反,lombok 将这些字段保留为空,并假设您知道自己在做什么。通常,您创建这些构造函数要么是因为框架要求您这样做,要么是因为框架将通过立即调用一组 setter 或反射性地更新这些字段来“修复”标记为 never null 的字段包含 null 值的问题。
@Setter 以及暗示它的 lombok 功能 (@Data)。
这些将以相同的方式对参数进行空检查。
@lombok.NonNull 一个参数
与前面的内容不同,此功能仅适用于lombok.NonNull,不适用于任何其他非空注释:这将在您的方法顶部添加一个空检查。
lombok 不为其他人这样做的原因是它的冲突:如果您将@NonNull 视为类型注释,那么它是在说:这个值不可能为空,它是有保证的,这与它的性质相反:现在空检查是编译器错误/警告!
这就像写作:
public void foo(String x) {
if (x != null && !(x instanceof String)) throw new IllegalArgumentException("x is not a string");
}
这应该是一个编译器错误/警告,因为它不可能发生并且只是无用的代码。如果您在一个非常严格的空值系统中工作,并且会被编译器无情地检查,@NonNull 可以暗示同样的事情,因此,我们不只是添加空值检查。
@Builder
是的,那会抛出 NPE。这是因为类上的@Builder 只是@AllArgsConstructor 的语法糖(如果标记为NonNull 的字段的参数为null,它将抛出NPE),然后将@Builder 放在该全参数构造函数上。因此,构建器不会进行空检查,但构建器的 .build() 调用将调用该构造函数,它会。