Encodera

Thanks for reading!

Donate to the site — we work hard for you.

How to create a builder for an object

Short answer

A builder assembles an object step by step. It is handy when there are many fields and some of them are optional:

record Pizza(String size, boolean cheese, boolean mushrooms) {
    static Builder builder() {
        return new Builder();
    }
 
    static class Builder {
        private String size = "medium";
        private boolean cheese;
        private boolean mushrooms;
 
        Builder size(String size) { this.size = size; return this; }
        Builder cheese() { this.cheese = true; return this; }
        Builder mushrooms() { this.mushrooms = true; return this; }
 
        Pizza build() {
            return new Pizza(size, cheese, mushrooms);
        }
    }
}
 
void main() {
    Pizza pizza = Pizza.builder().size("large").cheese().build();
    IO.println(pizza);
}

Output:

Pizza[size=large, cheese=true, mushrooms=false]

Each method returns this, so the calls can be chained.

Required fields

Check the required values in build():

record Email(String to, String subject) {
    static class Builder {
        private String to;
        private String subject = "(no subject)";
 
        Builder to(String to) { this.to = to; return this; }
        Builder subject(String subject) { this.subject = subject; return this; }
 
        Email build() {
            if (to == null) {
                throw new IllegalStateException("recipient is required");
            }
            return new Email(to, subject);
        }
    }
}
 
void main() {
    IO.println(new Email.Builder().to("anna@site.com").build());
    new Email.Builder().subject("Hi").build();
}

Output:

Email[to=anna@site.com, subject=(no subject)]
Exception in thread "main" java.lang.IllegalStateException: recipient is required

Common mistake

Writing a builder for an object with two or three fields. A builder is a lot of code; for small objects a record with a constructor is enough. In the Lombok library, the @Builder annotation generates a builder for you.

Functions used in this recipe

  • record — Declares a record — an immutable data class with ready-made equals(), hashCode() and toString().
  • static — Makes a field or method belong to the class itself rather than to each object.

Thanks for reading!

Donate to the site — we work hard for you.