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 requiredCommon 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.