lombok中的默认值。如何使用构造函数和构建器初始化

时间:2017-12-19 09:38:12

标签: java lombok

我有一个对象

@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

9 个答案:

答案 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(...)

检查相应的讨论:https://github.com/rzwitserloot/lombok/issues/1347

答案 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;
    }
}