@NonNull 会在使用@NoArgsConstructor 时出错吗?
Will @NonNull give an error on using @NoArgsConstructor?
@Getter
@Setter
@NoArgsConstructor
public class Company {
@NonNull
private String location;
@NonNull
private String name;
}
现在如果我写类似 -
Company company = new Company();
company.setLocation("Florida");
company.setName("ABC");
问题 1 - 在第 1 行我会得到一个错误,因为创建了一个新对象但位置和名称为空并且它们用 @NonNull
注释?
问题 2 - 我会在第 2 行和第 3 行遇到任何错误吗?
这很复杂,因为 java 社区以不同的方式处理 null,而 'non null' 意味着不同的事情:例如,在 DB 模型中 class 它可能意味着: CREATE TABLE
如果您要求数据库框架为您创建表,它会生成语句,应该在 SQL 中添加一个 NOT NULL 约束。然而,由于 POJO 也应该能够表示半构建的行(例如,表示数据库中 unid 列的 unid 字段包含 null
,因为重点是让数据库使用它的自动序列来填充它,直到你save()
它才会发生,因此java-side那个字段可以并且通常是 null !
因此,lombok 的 NonNull 支持有 4 个方面非常不同:
@RequiredArgsConstructor
和 @AllArgsConstructor
,以及暗示其中之一的所有 lombok 功能(@Builder
、@Data
和 @Value
)。
Lombok 将 final
或 的任何字段都视为具有某种 NonNull
注释,它特别识别为暗示任何对象都不应该甚至存在于该字段为空的地方(特别是 排除 JPA 的 NotNull!),并且可以在 lombok.config
中配置,但是 lombok 附带了一组开箱即用的已知注释集,作为 'required'.
'required' 字段具有以下属性:
@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 将这些字段保留为空,并假定您知道自己在做什么。通常,您制作这些构造函数是因为框架要求您这样做,或者因为框架会 'fix' 通过立即调用一堆 setter 或反射更新这些字段来将字段标记为永不为 null 且包含空值的问题.
@Setter
以及暗示它的 lombok 功能 (@Data
)。
这些将以相同的方式对参数进行空检查。
@lombok.NonNull
参数
与之前的内容不同,此功能仅适用于 lombok.NonNull
而不适用于任何其他非空注释:这将在您的方法顶部添加空值检查。
lombok 不为其他人这样做的原因是它有冲突:如果您将 @NonNull
视为类型注释,那么它说:这个值不可能为 null,这是有保证的,这与它的本质:现在空检查是一个编译器 error/warning!
就像写作:
public void foo(String x) {
if (x != null && !(x instanceof String)) throw new IllegalArgumentException("x is not a string");
}
那应该是一个编译器 error/warning 因为它不可能发生而且只是无用的代码。如果你在一个非常严格的 nullity 系统中工作,你的编译器会无情地检查它,@NonNull
可能意味着同样的事情,因此,我们不只是添加 null 检查。
@Builder
是的,那会抛出 NPE。这是因为 class 上的 @Builder
只是语法糖:@AllArgsConstructor
(如果标记为 NonNull 的字段的参数为 null,则将抛出 NPE),然后将 @Builder
在那个全参数构造函数上。因此,构建器不进行空检查,但构建器的 .build()
调用将调用该构造函数,它会调用。
@Getter
@Setter
@NoArgsConstructor
public class Company {
@NonNull
private String location;
@NonNull
private String name;
}
现在如果我写类似 -
Company company = new Company();
company.setLocation("Florida");
company.setName("ABC");
问题 1 - 在第 1 行我会得到一个错误,因为创建了一个新对象但位置和名称为空并且它们用 @NonNull
注释?
问题 2 - 我会在第 2 行和第 3 行遇到任何错误吗?
这很复杂,因为 java 社区以不同的方式处理 null,而 'non null' 意味着不同的事情:例如,在 DB 模型中 class 它可能意味着: CREATE TABLE
如果您要求数据库框架为您创建表,它会生成语句,应该在 SQL 中添加一个 NOT NULL 约束。然而,由于 POJO 也应该能够表示半构建的行(例如,表示数据库中 unid 列的 unid 字段包含 null
,因为重点是让数据库使用它的自动序列来填充它,直到你save()
它才会发生,因此java-side那个字段可以并且通常是 null !
因此,lombok 的 NonNull 支持有 4 个方面非常不同:
@RequiredArgsConstructor
和 @AllArgsConstructor
,以及暗示其中之一的所有 lombok 功能(@Builder
、@Data
和 @Value
)。
Lombok 将 final
或 的任何字段都视为具有某种 NonNull
注释,它特别识别为暗示任何对象都不应该甚至存在于该字段为空的地方(特别是 排除 JPA 的 NotNull!),并且可以在 lombok.config
中配置,但是 lombok 附带了一组开箱即用的已知注释集,作为 'required'.
'required' 字段具有以下属性:
@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 将这些字段保留为空,并假定您知道自己在做什么。通常,您制作这些构造函数是因为框架要求您这样做,或者因为框架会 'fix' 通过立即调用一堆 setter 或反射更新这些字段来将字段标记为永不为 null 且包含空值的问题.
@Setter
以及暗示它的 lombok 功能 (@Data
)。
这些将以相同的方式对参数进行空检查。
@lombok.NonNull
参数
与之前的内容不同,此功能仅适用于 lombok.NonNull
而不适用于任何其他非空注释:这将在您的方法顶部添加空值检查。
lombok 不为其他人这样做的原因是它有冲突:如果您将 @NonNull
视为类型注释,那么它说:这个值不可能为 null,这是有保证的,这与它的本质:现在空检查是一个编译器 error/warning!
就像写作:
public void foo(String x) {
if (x != null && !(x instanceof String)) throw new IllegalArgumentException("x is not a string");
}
那应该是一个编译器 error/warning 因为它不可能发生而且只是无用的代码。如果你在一个非常严格的 nullity 系统中工作,你的编译器会无情地检查它,@NonNull
可能意味着同样的事情,因此,我们不只是添加 null 检查。
@Builder
是的,那会抛出 NPE。这是因为 class 上的 @Builder
只是语法糖:@AllArgsConstructor
(如果标记为 NonNull 的字段的参数为 null,则将抛出 NPE),然后将 @Builder
在那个全参数构造函数上。因此,构建器不进行空检查,但构建器的 .build()
调用将调用该构造函数,它会调用。