Daniel Lubarov

Writing Java builders like a pro

This is my preferred approach to Java builders. To illustrate, here's a class representing an HTTP cookie.

public final class Cookie {
  public static final class Builder {
    private Option<String> name = Option.none();
    private Option<String> value = Option.none();
    private Option<Instant> expires = Option.none();

    public Builder setName(String name) {
      this.name = Option.some(name);
      return this;
    }

    public Builder setValue(String value) {
      this.value = Option.some(value);
      return this;
    }

    public Builder setExpires(Instant expires) {
      this.expires = Option.some(expires);
      return this;
    }

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

  private final String name;
  private final String value;
  private final Option<Instant> expires;

  private Cookie(Builder builder) {
    name = builder.name.getOrThrow("No name was set.");
    value = builder.value.getOrThrow("No value was set.");
    expires = builder.expires;
  }

  public String getName() {
    return name;
  }

  public String getValue() {
    return value;
  }

  public Option<Instant> getExpires() {
    return expires;
  }
}

I like this because

  • The Cookie class is immutable. Not just "externally immutable" in the sense of not exposing mutators, but internally immutable as well.
  • There are no "nullable" fields. Option is the more type-safe alternative
  • The user will get a descriptive error if they forget to set a required field. And we accomplish this without needing a bunch of conditional blocks.