Software Engineer's Blog

Understanding Lombok’s @Builder and Default Field Values

Understanding Lombok’s @Builder and Default Field Values

Lombok’s @Builder annotation is a powerful way to implement the builder pattern without writing repetitive code. However, if you set a default value for a field, you may see this warning:

java: @Builder will ignore the initializing expression entirely. 
If you want the initializing expression to serve as default, add @Builder.Default. 
If it is not supposed to be settable during building, make the field final.

Let’s break down why this happens and how to fix it.

Why Lombok Ignores Field Defaults

When you use @Builder, Lombok generates a separate inner Builder class (e.g., UserBuilder) at compile time. This builder is used when you call User.builder().

The key point: fields in the original class and the Builder class are separate.

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class User {
    private String name;
    private int age = 18; // Default value for User
}

Here, age = 18 works when creating a User object directly. But in the builder, the age field defaults to 0 (the default int value) because the Builder class doesn’t know about the original initialization.

This is why Lombok warns that it “will ignore the initializing expression entirely.”

Solution 1: Use @Builder.Default

The easiest solution is to annotate the field with @Builder.Default. This ensures the builder uses the default value if no value is explicitly set.

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class User {
    private String name;

    @Builder.Default
    private int age = 18;
}

Now, if you build a user without specifying age, it will default to 18:

User user = User.builder().name("Alice").build();
System.out.println(user.getAge()); // 18

You can also use @Builder.Default with objects, like lists or maps:

@Builder.Default
private List<String> tags = new ArrayList<>();

Solution 2: Make the Field final

If the field should never change after object creation, declare it as final.

@Getter
@Builder
public class User {
    private String name;
    private final int age = 18;
}

Characteristics of final fields:

  • Must be initialized at declaration or in the constructor.
  • The builder cannot override this value. Any call like builder.age(20) will fail.
  • Use this approach when the field should always have a fixed value.

Key Takeaways

  • @Builder generates a separate builder class, so initial field values are ignored by default.
  • Use @Builder.Default to apply default values to builder fields.
  • Use final when the field’s value should never change via the builder.

This simple adjustment keeps your Lombok builders working correctly while preserving default values.