Below are some reasons arguing for the use of the pattern and example code in Java, but it is an implementation of the Builder Pattern covered by the Gang of Four in Design Patterns. The reasons you would use it in Java are also applicable to other programming languages as well.

As Joshua Bloch states in Effective Java, 2nd Edition:

The builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters.

We've all at some point encountered a class with a list of constructors where each addition adds a new option parameter:

Pizza(int size) { ... }        
Pizza(int size, boolean cheese) { ... }    
Pizza(int size, boolean cheese, boolean pepperoni) { ... }    
Pizza(int size, boolean cheese, boolean pepperoni, boolean bacon) { ... }

This is called the Telescoping Constructor Pattern. The problem with this pattern is that once constructors are 4 or 5 parameters long it becomes difficult to remember the required order of the parameters as well as what particular constructor you might want in a given situation.

One alternative you have to the Telescoping Constructor Pattern is the JavaBean Pattern where you call a constructor with the mandatory parameters and then call any optional setters after:

Pizza pizza = new Pizza(12);
pizza.setCheese(true);
pizza.setPepperoni(true);
pizza.setBacon(true);

The problem here is that because the object is created over several calls it may be in an inconsistent state partway through its construction. This also requires a lot of extra effort to ensure thread safety.

The better alternative is to use the Builder Pattern.

public class Pizza {
  private int size;
  private boolean cheese;
  private boolean pepperoni;
  private boolean bacon;

  public static class Builder {
    //required
    private final int size;

    //optional
    private boolean cheese = false;
    private boolean pepperoni = false;
    private boolean bacon = false;

    public Builder(int size) {
      this.size = size;
    }

    public Builder cheese(boolean value) {
      cheese = value;
      return this;
    }

    public Builder pepperoni(boolean value) {
      pepperoni = value;
      return this;
    }

    public Builder bacon(boolean value) {
      bacon = value;
      return this;
    }

    public Pizza build() {
      return new Pizza(this);
    }
  }

  private Pizza(Builder builder) {
    size = builder.size;
    cheese = builder.cheese;
    pepperoni = builder.pepperoni;
    bacon = builder.bacon;
  }
}

Note that Pizza is immutable and that parameter values are all in a single location. Because the Builder's setter methods return the Builder object they are able to be chained.

Pizza pizza = new Pizza.Builder(12)
                       .cheese(true)
                       .pepperoni(true)
                       .bacon(true)
                       .build();

This results in code that is easy to write and very easy to read and understand. In this example, the build method could be modified to check parameters after they have been copied from the builder to the Pizza object and throw an IllegalStateException if an invalid parameter value has been supplied. This pattern is flexible and it is easy to add more parameters to it in the future. It is really only useful if you are going to have more than 4 or 5 parameters for a constructor. That said, it might be worthwhile in the first place if you suspect you may be adding more parameters in the future.

I have borrowed heavily on this topic from the book Effective Java, 2nd Edition by Joshua Bloch. To learn more about this pattern and other effective Java practices I highly recommend it.

Answer from user2628 on Stack Overflow
🌐
Baeldung
baeldung.com › home › java › implement the builder pattern in java
Implement the Builder Pattern in Java | Baeldung
April 22, 2024 - Lombok is a library that simplifies Java code by automatically generating common methods such as getters, setters, equals, hashCode, and even constructors. One of the most appreciated features of Lombok is its support for the Builder Pattern. By annotating a class with @Builder, Lombok generates a builder class with fluent methods for setting properties.
🌐
GeeksforGeeks
geeksforgeeks.org › java › builder-pattern-in-java
Builder Method Design Pattern in Java - GeeksforGeeks
July 11, 2025 - The below example can lead us to a Student instance in an inconsistent state, for example, a student with name Ram and address Delhi. ... Note : Try running main method statements in loop(i.e. multiple requests to server simultaneously). To solve this problem, there is Builder pattern to ensure the thread-safety and atomicity of object creation.
Top answer
1 of 13
1162

Below are some reasons arguing for the use of the pattern and example code in Java, but it is an implementation of the Builder Pattern covered by the Gang of Four in Design Patterns. The reasons you would use it in Java are also applicable to other programming languages as well.

As Joshua Bloch states in Effective Java, 2nd Edition:

The builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters.

We've all at some point encountered a class with a list of constructors where each addition adds a new option parameter:

Pizza(int size) { ... }        
Pizza(int size, boolean cheese) { ... }    
Pizza(int size, boolean cheese, boolean pepperoni) { ... }    
Pizza(int size, boolean cheese, boolean pepperoni, boolean bacon) { ... }

This is called the Telescoping Constructor Pattern. The problem with this pattern is that once constructors are 4 or 5 parameters long it becomes difficult to remember the required order of the parameters as well as what particular constructor you might want in a given situation.

One alternative you have to the Telescoping Constructor Pattern is the JavaBean Pattern where you call a constructor with the mandatory parameters and then call any optional setters after:

Pizza pizza = new Pizza(12);
pizza.setCheese(true);
pizza.setPepperoni(true);
pizza.setBacon(true);

The problem here is that because the object is created over several calls it may be in an inconsistent state partway through its construction. This also requires a lot of extra effort to ensure thread safety.

The better alternative is to use the Builder Pattern.

public class Pizza {
  private int size;
  private boolean cheese;
  private boolean pepperoni;
  private boolean bacon;

  public static class Builder {
    //required
    private final int size;

    //optional
    private boolean cheese = false;
    private boolean pepperoni = false;
    private boolean bacon = false;

    public Builder(int size) {
      this.size = size;
    }

    public Builder cheese(boolean value) {
      cheese = value;
      return this;
    }

    public Builder pepperoni(boolean value) {
      pepperoni = value;
      return this;
    }

    public Builder bacon(boolean value) {
      bacon = value;
      return this;
    }

    public Pizza build() {
      return new Pizza(this);
    }
  }

  private Pizza(Builder builder) {
    size = builder.size;
    cheese = builder.cheese;
    pepperoni = builder.pepperoni;
    bacon = builder.bacon;
  }
}

Note that Pizza is immutable and that parameter values are all in a single location. Because the Builder's setter methods return the Builder object they are able to be chained.

Pizza pizza = new Pizza.Builder(12)
                       .cheese(true)
                       .pepperoni(true)
                       .bacon(true)
                       .build();

This results in code that is easy to write and very easy to read and understand. In this example, the build method could be modified to check parameters after they have been copied from the builder to the Pizza object and throw an IllegalStateException if an invalid parameter value has been supplied. This pattern is flexible and it is easy to add more parameters to it in the future. It is really only useful if you are going to have more than 4 or 5 parameters for a constructor. That said, it might be worthwhile in the first place if you suspect you may be adding more parameters in the future.

I have borrowed heavily on this topic from the book Effective Java, 2nd Edition by Joshua Bloch. To learn more about this pattern and other effective Java practices I highly recommend it.

2 of 13
352

Consider a restaurant. The creation of "today's meal" is a factory pattern, because you tell the kitchen "get me today's meal" and the kitchen (factory) decides what object to generate, based on hidden criteria.

The builder appears if you order a custom pizza. In this case, the waiter tells the chef (builder) "I need a pizza; add cheese, onions and bacon to it!" Thus, the builder exposes the attributes the generated object should have, but hides how to set them.

🌐
Medium
serpro69.medium.com › the-builder-pattern-in-java-2c03fc6ccd16
The Builder pattern in Java — yet another Builder Pattern article? | by Serhii Prodan | Medium
April 1, 2019 - Overall, the Builder pattern is a very commonly used technique for creating objects and is a good choice to use when classes have constructors with multiple parameters (especially optional ones) and are likely to change in the future. The code becomes much easier to write and read as compared to overridden constructors, and the class scales just as well as JavaBeans but is much safer.
🌐
Refactoring.Guru
refactoring.guru › home › design patterns › builder › java
Builder in Java / Design Patterns
January 1, 2026 - java.nio.ByteBuffer#put() (also in CharBuffer, ShortBuffer, IntBuffer, LongBuffer, FloatBuffer and DoubleBuffer) ... Identification: The Builder pattern can be recognized in a class, which has a single creation method and several methods to configure the resulting object. Builder methods often support chaining (for example, someBuilder.setValueA(1).setValueB(2).create()).
🌐
DEV Community
dev.to › zeeshanali0704 › builder-design-pattern-in-java-a-complete-guide-2l41
Builder Design Pattern in Java – A Complete Guide - DEV Community
October 30, 2025 - User user = new User.Builder("John", "Doe") .age(30) .email("john@example.com") .build(); // Main.java package org.example; public class Main { public static void main(String[] args) { UserBuilder builder = new UserBuilder(); UserDirector director ...
🌐
Project Lombok
projectlombok.org › features › Builder
@Builder
The sorted collections (java.util: ... that the type argument of the collection has natural order (implements java.util.Comparable). There is no way to pass an explicit Comparator to use in the builder....
🌐
DigitalOcean
digitalocean.com › community › tutorials › builder-design-pattern-in-java
Builder Design Pattern in Java: Guide & Examples | DigitalOcean
August 3, 2022 - Java Builder class should have methods to set the optional parameters and it should return the same Builder object after setting the optional attribute. The final step is to provide a build() method in the builder class that will return the Object needed by client program. For this we need to have a private constructor in the Class with Builder class as argument. Here is the sample builder pattern example code where we have a Computer class and ComputerBuilder class to build it.
Find elsewhere
🌐
LangChain4j
glaforge.dev › posts › 2024 › 01 › 16 › java-functional-builder-approach
Functional builder approach in Java | Guillaume Laforge
January 16, 2024 - Learn how a functional builder approach, inspired by Golang, can simplify verbose Java object creation and deeply nested builder patterns.
Top answer
1 of 6
96

The GenericBuilder

The idea for building mutable objects (immutable objects are addressed later on) is to use method references to setters of the instance that should be built. This leads us to a generic builder that is capable of building every POJO with a default constructor - one builder to rule them all ;-)

The implementation is this:

public class GenericBuilder<T> {

    private final Supplier<T> instantiator;

    private List<Consumer<T>> instanceModifiers = new ArrayList<>();

    public GenericBuilder(Supplier<T> instantiator) {
        this.instantiator = instantiator;
    }

    public static <T> GenericBuilder<T> of(Supplier<T> instantiator) {
        return new GenericBuilder<T>(instantiator);
    }

    public <U> GenericBuilder<T> with(BiConsumer<T, U> consumer, U value) {
        Consumer<T> c = instance -> consumer.accept(instance, value);
        instanceModifiers.add(c);
        return this;
    }

    public T build() {
        T value = instantiator.get();
        instanceModifiers.forEach(modifier -> modifier.accept(value));
        instanceModifiers.clear();
        return value;
    }
}

The builder is constructed with a supplier that creates new instances and then those instances are modified by the modifications specified with the with method.

The GenericBuilder would be used for Person like this:

Person value = GenericBuilder.of(Person::new)
            .with(Person::setName, "Otto").with(Person::setAge, 5).build();

Properties and further Usages

But there is more about that builder to discover.

For example, the above implementation clears the modifiers. This could be moved into its own method. Therefore, the builder would keep its state between modifications and it would be easy create multiple equal instances. Or, depending on the nature of an instanceModifier, a list of varying objects. For example, an instanceModifier could read its value from an increasing counter.

Continuing with this thought, we could implement a fork method that would return a new clone of the GenericBuilder instance that it is called on. This is easily possible because the state of the builder is just the instantiator and the list of instanceModifiers. From there on, both builders could be altered with some other instanceModifiers. They would share the same basis and have some additional state set on built instances.

The last point I consider especially helpful when needing heavy entities for unit or even integration tests in enterprise applications. There would be no god-object for entities, but for builders instead.

The GenericBuilder can also replace the need for different test value factories. In my current project, there are many factories used for creating test instances. The code is tightly coupled to different test scenarios and it is difficult to extract portions of a test factory for reuse in another test factory in a slightly different scenario. With the GenericBuilder, reusing this becomes much easier as there is only a specific list of instanceModifiers.

To verify that created instances are valid, the GenericBuilder could be initialized with a set of predicates, which are verified in the build method after all instanceModifiers are run.

public T build() {
    T value = instantiator.get();
    instanceModifiers.forEach(modifier -> modifier.accept(value));
    verifyPredicates(value);
    instanceModifiers.clear();
    return value;
}

private void verifyPredicates(T value) {
    List<Predicate<T>> violated = predicates.stream()
            .filter(e -> !e.test(value)).collect(Collectors.toList());
    if (!violated.isEmpty()) {
        throw new IllegalStateException(value.toString()
                + " violates predicates " + violated);
    }
}

Immutable object creation

To use the above scheme for the creation of immutable objects, extract the state of the immutable object into a mutable object and use the instantiator and builder to operate on the mutable state object. Then, add a function that will create a new immutable instance for the mutable state. However, this requires that the immutable object either has its state encapsulated like this or it be changed in that fashion (basically applying parameter object pattern to its constructor).

This is in some way different than a builder was used in pre-java-8 times. There, the builder itself was the mutable object that created a new instance at the end. Now, we have a separation of the state a builder keeps in a mutable object and the builder functionality itself.

In essence
Stop writing boilerplate builder patterns and get productive using the GenericBuilder.

2 of 6
11
public class PersonBuilder {
    public String salutation;
    public String firstName;
    public String middleName;
    public String lastName;
    public String suffix;
    public Address address;
    public boolean isFemale;
    public boolean isEmployed;
    public boolean isHomewOwner;

    public PersonBuilder with(
        Consumer<PersonBuilder> builderFunction) {
        builderFunction.accept(this);
        return this;
    }


    public Person createPerson() {
        return new Person(salutation, firstName, middleName,
                lastName, suffix, address, isFemale,
                isEmployed, isHomewOwner);
    }
}

Usage

Person person = new PersonBuilder()
    .with($ -> {
        $.salutation = "Mr.";
        $.firstName = "John";
        $.lastName = "Doe";
        $.isFemale = false;
    })
    .with($ -> $.isHomewOwner = true)
    .with($ -> {
        $.address =
            new PersonBuilder.AddressBuilder()
                .with($_address -> {
                    $_address.city = "Pune";
                    $_address.state = "MH";
                    $_address.pin = "411001";
                }).createAddress();
    })
    .createPerson();

Refer: https://medium.com/beingprofessional/think-functional-advanced-builder-pattern-using-lambda-284714b85ed5

Disclaimer: I am the author of the post

🌐
DEV Community
dev.to › wkreuch › the-builder-design-pattern-in-java-167l
The Builder Design Pattern in Java - DEV Community
July 10, 2025 - Below is an example of a RestTemplate configuration using a custom RestTemplateBuilder to configure HTTP client settings: @Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate() { return new RestTemplateBuilder() .setConnectTimeout(Duration.ofSeconds(5)) .setReadTimeout(Duration.ofSeconds(10)) .build(); } } The Builder Pattern in Java, including in Spring Boot, solves the problem of constructing complex objects by providing a clean, step-by-step approach.
🌐
Google Translate
translate.google.com › translate
Builder Pattern in Java: Crafting Custom Objects with Clarity | Java Design Patterns
In this Java Builder pattern example, we construct different types of Hero objects with varying attributes.
🌐
Google Translate
translate.google.com › translate
How to implement a simple Builder Pattern in java | by Isaac Ssemugenyi | Medium
January 7, 2024 - Looking at this.make= builder.make;, it assigns the value of make from Builder class to the make property of the Car class, copying the value from the builder to the actual object being constructed.
🌐
YouTube
youtube.com › watch
Java Builder Pattern Explained in 3 Minutes - YouTube
Java Builder Pattern ExplainedThe builder pattern in Java is a powerful way to construct objects with many fields. A Java builder lets you provide a flexible...
Published   January 22, 2024
Top answer
1 of 2
3

First one seems worse. The original builder can subsequently be used to modify the state of the built object, since it still holds a reference to it.

MazeBuilder builder = new MazeBuilderImpl();
Maze maze = builder.rooms(1).build();
builder.rooms(2); // modifies the state of maze ...

The copy in the second one prevents that from happening, and allows the builder to be reused.

Both are bad though, since Maze is implied to be mutable. Builders are best for building immutable objects. It requires re-declaring the fields of Maze as fields of MazeBuilder, i.e. if Maze has a String id field, so will MazeBuilder. Lombok can help with reducing that boilerplate.

2 of 2
1

If you return same object as in builder as follow:

@Override
public Maze build() {
    return maze;
}

then you will be referencing same object present in builder. And it can be still muted (changed). So your object could be still changes from somewhere. It still one object that you can affect directly or throuht builder.

If you return different object, you dont have to worry about builder affecting it after calling build().

But if your object can be immutable, then its common to have copy of objects fields in builder and construct object in build() method.

public class MazeBuilderImpl implements MazeBuilder {

    private Room roomA;
    private Room roomB;
    private Door doorA;
    private Door doorB;
    ....


    // adding rooms, doors etc.

    @Override
    public Maze build() {
        return new Maze(roomA, roomB, doorA, doorB, ...);
    }
}
🌐
YouTube
youtube.com › watch
PATRÓN de DISEÑO BUILDER en JAVA - Tutorial Completo Fácil - YouTube
👨‍💻 CodeJa | Aprende JAVA con EJERCICIOS - https://codeja.dev/📱 TikTok: https://www.tiktok.com/@programandoenjava💬 Discord: https://discord.gg/K3CeetMx2r...
Published   April 26, 2023
🌐
Java By Examples
javabyexamples.com › delombok-builder
Home | Java By Examples
When we annotate a class with @Builder, Lombok creates a builder for all instance fields in that class.