我有一个对象
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
private boolean isEmailConfirmed = true;
}
我用两种方式初始化它
UserInfo ui = new UserInfo();
UserInfo ui2 = UserInfo.builder().build();
System.out.println("ui: " + ui.isEmailConfirmed());
System.out.println("ui2: " + ui2.isEmailConfirmed());
这是输出
ui: true
ui2: false
似乎构建器没有获得默认值。我将@Builder.Default
注释添加到我的属性中,我的对象现在看起来像这样
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
@Builder.Default
private boolean isEmailConfirmed = true;
}
这是控制台输出
ui: false
ui2: true
如何让它们成为true
?
答案 0 :(得分:29)
自@Builder.Default
annotation is broken以来,我根本不会使用它。但是,您可以使用以下方法:
@Data
@NoArgsConstructor
public class UserInfo {
private int id;
private String nick;
private boolean isEmailConfirmed = true;
@Builder
@SuppressWarnings("unused")
private UserInfo(int id, String nick, Boolean isEmailConfirmed) {
this.id = id;
this.nick = nick;
this.isEmailConfirmed = Optional.ofNullable(isEmailConfirmed).orElse(this.isEmailConfirmed);
}
}
这样你可以确保:
isEmailConfirmed
仅在一个位置初始化,使代码不易出错,以后更容易维护UserInfo
类将以与使用构建器或无参数构造函数相同的方式初始化换句话说,条件保持true
:
new UserInfo().equals(UserInfo.builder().build())
在这种情况下,无论您如何创建对象,对象创建都是一致的。当你的类没有被映射框架或JPA提供者使用时,尤其重要的是当你没有由构建器手动实例化它时,而是在你的背后调用no-args构造函数来创建实例。
方法described above非常相似,但它有一个主要缺点。您必须在两个地方初始化字段,这会使代码容易出错,因为您需要保持值一致。
答案 1 :(得分:17)
我的猜测是,这是不可能的(没有删除代码)。但是你为什么不实现你需要的构造函数呢?龙目岛旨在让您的生活更轻松,如果某些东西不能与龙目岛一起使用,那就按照老式的方式进行。
@Data
@Builder
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
@Builder.Default
private boolean isEmailConfirmed = true;
public UserInfo(){
isEmailConfirmed = true;
}
}
控制台输出:
ui: true
ui2: true
答案 2 :(得分:2)
在版本1.18.2中,@NoArgsConstructor
和@Builder
都可以运行,但不能完全正常。
具有一个或多个字段的构造函数将使所有其他默认初始化为空:new UserInfo("Some nick")
将导致isEmailConfirmed
再次为假。
我的解决方法是:
public UserInfo(String nick) {
this();
this.nick = nick;
}
这样,所有默认字段都将被初始化,我们将获得预期的构造函数。
答案 3 :(得分:1)
另一种方法是定义你自己的 getter 方法覆盖 lombok getter:
@Data
@Builder
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
private Boolean isEmailConfirmed;
public Boolean getIsEmailConfirmed(){
return Objects.isNull(isEmailConfirmed) ? true : isEmailConfirmed;
}
}
答案 4 :(得分:1)
我的经验是,@Builder
在实例化类的唯一方法时效果最佳,因此在与@Value
而非@Data
配对时效果最佳。
对于所有字段仍然可以任意顺序可变并且想要保留链接调用的类,请考虑将其替换为@Accessors(chain=true)
或@Accessors(fluent=true)
。
@Data
@Accessors(fluent=true)
public class UserInfo {
private int id;
private String nick;
private boolean isEmailConfirmed = true;
}
这使您可以在代码中流畅地构造对象,并避免不必要地创建Builder对象:
UserInfo ui = new UserInfo().id(25).nick("John");
答案 5 :(得分:0)
这是我的方法:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
public class UserInfo {
private int id;
private String nick;
private boolean isEmailConfirmed = true;
}
然后
UserInfo ui = new UserInfo().toBuilder().build();
答案 6 :(得分:0)
自定义构造函数和print
可能永远无法一起工作。
框架作者希望避免对@Builder.Default
进行两次初始化。
我通过@Builder
方法重用了.builder()
:
public static CLAZZ of(...)
答案 7 :(得分:0)
初始化No-Arg Constructor
中的属性
已转换
private boolean isEmailConfirmed = true;
到
public class UserInfo {
public UserInfo() {
this.isEmailConfirmed = true;
}
}
答案 8 :(得分:0)
您可以创建一个带有默认值的静态Builder类:
@Data
@Builder(builderClassName="Builder")
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
private int id;
private String nick;
private boolean isEmailConfirmed;
public static class Builder{
//Set defaults here
private boolean isEmailConfirmed = true;
}
}