Default value in lombok. How to init default with both constructor and builder

We Are Going To Discuss About Default value in lombok. How to init default with both constructor and builder. So lets Start this Java Article.

Default value in lombok. How to init default with both constructor and builder

  1. Default value in lombok. How to init default with both constructor and builder

    My guess is that it's not possible (without having delomboked the code). But why don't you just implement the constructor you need? Lombok is meant to make your life easier, and if something won't work with Lombok, just do it the old fashioned way.

  2. Default value in lombok. How to init default with both constructor and builder

    My guess is that it's not possible (without having delomboked the code). But why don't you just implement the constructor you need? Lombok is meant to make your life easier, and if something won't work with Lombok, just do it the old fashioned way.

Solution 1

My guess is that it’s not possible (without having delomboked the code). But why don’t you just implement the constructor you need? Lombok is meant to make your life easier, and if something won’t work with Lombok, just do it the old fashioned way.

@Data
@Builder
@AllArgsConstructor
public class UserInfo { 
    private int id;
    private String nick;
    @Builder.Default
    private boolean isEmailConfirmed = true;
    
    public UserInfo(){
        isEmailConfirmed = true;
    }
}

Console output:

ui: true
ui2: true

Update
As of 01/2021, this bug seems to be fixed in Lombok, at least for generated constructors. Note that there is still a similar issue when you mix Builder.Default and explicit constructors.

Original Author Michael A. Schaffrath Of This Content

Solution 2

Since the @Builder.Default annotation is broken, I wouldn’t use it at all. You can, however, use the following approach by moving the @Builder annotation from class level to the custom constructor:

@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);
    }
}

This way you ensure:

  • the field isEmailConfirmed is initialized only in one place making the code less error-prone and easier to maintain later
  • the UserInfo class will be initialized the same way either you use a builder or a no-args constructor

In other words, the condition holds true:

new UserInfo().equals(UserInfo.builder().build())

In that case, the object creation is consistent no matter how you create it. It is especially important when your class is used by a mapping framework or by JPA provider when you are not instantiating it manually by a builder but a no-args constructor is invoked behind your back to create the instance.

The approach described above is very similar but it has a major drawback. You have to initialize the field in two places which makes the code error-prone as you are required to keep the values consistent.

Original Author Marcin Kłopotek Of This Content

Solution 3

Another way is define your own getter method overriding the 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;
    }
}

Original Author Sahil Chhabra Of This Content

Solution 4

My experience is that @Builder works best when it is the only means of instantiating a class, and therefore works best when paired with @Value rather than @Data.

For classes where all fields are mutable in any order anyway, and for which you want to keep the chained calls, consider replacing it with @Accessors(chain=true) or @Accessors(fluent=true).

@Data
@Accessors(fluent=true)
public class UserInfo {
    private int id;
    private String nick;
    private boolean isEmailConfirmed = true;
}

This allows you to construct your objects fluently in the code, and avoid un-necessary creation of Builder objects:

UserInfo ui = new UserInfo().id(25).nick("John");

Original Author LordOfThePigs Of This Content

Conclusion

So This is all About This Tutorial. Hope This Tutorial Helped You. Thank You.

Also Read,

Siddharth

I am an Information Technology Engineer. I have Completed my MCA And I have 4 Year Plus Experience, I am a web developer with knowledge of multiple back-end platforms Like PHP, Node.js, Python and frontend JavaScript frameworks Like Angular, React, and Vue.

Leave a Comment