龙目岛中的默认值。如何使用构造函数和生成器初始化默认值

2022-08-31 12:16:55

我有一个对象

@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


答案 1

我的猜测是这是不可能的(如果没有对代码进行解密)。但是,为什么不直接实现所需的构造函数呢?龙目岛旨在让你的生活更轻松,如果龙目岛的某些事情不起作用,那就用老式的方式去做吧。

@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

更新
截至2021年1月1日,此错误似乎已在龙目岛中修复,至少对于生成的构造函数而言。请注意,混合和显式构造函数时仍然存在类似的问题Builder.Default


答案 2

由于@Builder.Default注释已损坏,因此我根本不会使用它。但是,您可以通过将批注从类级别移动到自定义构造函数来使用以下方法:@Builder

@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 构造函数来创建实例时,这一点尤其重要。

上面描述的方法非常相似,但它有一个主要缺点。您必须在两个位置初始化字段,这使得代码容易出错,因为您需要保持值的一致性。


推荐