Writing clean, maintainable Java code often comes down to reducing boilerplate and improving readability. One common struggle developers encounter is constructing complex objects — especially those with many optional parameters. This is where Lombok’s @Builder annotation shines.
In this post, we’ll explore how Lombok simplifies the builder design pattern, and why you might want to use it in your projects.
The Problem Statement: Too Many Constructors
Imagine you have a simple class like this:
public class User { private String name; private int age; private String email; private String addressLine1; private String addressLine2;}
To initialize this class, you might end up with:
- Multiple constructors (if some fields are optional)
- Setters for each field
- Confusing parameter ordering
This quickly becomes hard to read and maintain:
User user = new User("John", 30, "john@example.com", "Some Street 123", "London");
What if you forget the order? What if some fields are optional?
The Builder Pattern to the Rescue
The Builder pattern solves this by performing step-by-step object construction:
User user = User.builder() .name("John") .age(30) .email("john@example.com") .addressLine1("Some Street 123") .addressLine2("London") .build();
This is much cleaner and easier to understand than remembering the ordering of parameters in the constructors of the class.
But still implementing the builder design pattern manually requires a lot of boilerplate code.
Enter Lombok’s @Builder
Project Lombok eliminates the need to write the builder yourself in most cases. Just add the annotation:
import lombok.Builder;import lombok.Data;@Data@Builderpublic class User { private String name; private int age; private String email; private String address;}
and the Lombok will generate additionally:
- A static
builder()method inUserclass - A
Builderinner class inside theUserclass - Fluent setter methods in the
Builderclass - A
build()method in theBuilderclass to construct the final object
Key Benefits
1. Readability
Builder makes object creation self-documenting:
User user = User.builder() .name("Alice") .email("alicelee@example.com") .build();
2. Immutability Support
When combined with @Value, you can create immutable objects easily:
@Value@Builderpublic class User { String name; int age;}
3. Optional Parameters
No need for multiple constructors – just set the values that you need.
4. Cleaner Codebase
Less boilerplate means less bugs and easier maintenance.
Advanced Features
Specifying Default Values
You can define defaults using @Builder.Default:
@Builder.Defaultprivate String role = "USER";
Adding Custom Builder Methods
You can customize parts of the builder if needed:
public static class UserBuilder { public UserBuilder name(String name) { this.name = name.toUpperCase(); return this; }}
The Lombok will utilise the user-defined builder class and will add other missing fields.
Cloning objects using ToBuilder
Enable cloning of the object and modification:
@Builder(toBuilder = true)
User updated = user.toBuilder() .email("new@email.com") .build();
When to Use @Builder
You may use @Builder annotation when:
- Your class has many parameters
- Constructor calls become unreadable or hard to maintain
- You want or just like a fluent API
It is better to avoid it when:
- The class is very simple (less than 3 fields)
- Performance and memory usage is extremely critical (builder adds slight overhead)
Conclusion
Lombok’s @Builder annotation is a powerful tool that helps you write cleaner and more maintainable Java code with minimal effort. By removing boilerplate and improving readability, it allows you to focus on what really matters which is your application logic.
If you’re not already using it, adding Lombok to your project might be one of the simplest ways to level up your Java development workflow.
