CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-google-auto-value--auto-value

Generated immutable value classes for Java 8+ using annotation processing

Pending
Overview
Eval results
Files

builders.mddocs/

Builder Pattern

AutoValue can generate builder classes that provide a fluent API for constructing value objects, especially useful for classes with many properties or optional fields.

Basic Builder

@AutoValue
public abstract class Person {
  public abstract String name();
  public abstract int age();
  public abstract Optional<String> email();
  
  public static Builder builder() {
    return new AutoValue_Person.Builder();
  }
  
  @AutoValue.Builder
  public abstract static class Builder {
    public abstract Builder name(String name);
    public abstract Builder age(int age);
    public abstract Builder email(String email);
    public abstract Person build();
  }
}

Usage Example

Person person = Person.builder()
    .name("Alice")
    .age(30)
    .email("alice@example.com")
    .build();

// Optional properties can be omitted
Person personWithoutEmail = Person.builder()
    .name("Bob")
    .age(25)
    .build();

Builder with Defaults

Set default values in the builder factory method:

@AutoValue
public abstract class Configuration {
  public abstract String host();
  public abstract int port();
  public abstract boolean ssl();
  public abstract int timeoutMs();
  
  public static Builder builder() {
    return new AutoValue_Configuration.Builder()
        .host("localhost")
        .port(8080)
        .ssl(false)
        .timeoutMs(5000);
  }
  
  @AutoValue.Builder
  public abstract static class Builder {
    public abstract Builder host(String host);
    public abstract Builder port(int port);
    public abstract Builder ssl(boolean ssl);
    public abstract Builder timeoutMs(int timeoutMs);
    public abstract Configuration build();
  }
}

Usage with defaults:

Configuration defaultConfig = Configuration.builder().build();
// host=localhost, port=8080, ssl=false, timeoutMs=5000

Configuration customConfig = Configuration.builder()
    .host("api.example.com")
    .ssl(true)
    .build();
// host=api.example.com, port=8080, ssl=true, timeoutMs=5000

Builder with Collections

Builders provide convenience methods for adding to collections:

@AutoValue
public abstract class Team {
  public abstract String name();
  public abstract ImmutableList<String> members();
  public abstract ImmutableSet<String> skills();
  
  public static Builder builder() {
    return new AutoValue_Team.Builder();
  }
  
  @AutoValue.Builder
  public abstract static class Builder {
    public abstract Builder name(String name);
    
    // Collection setters
    public abstract Builder members(Iterable<String> members);
    public abstract Builder skills(Iterable<String> skills);
    
    // Individual item adders (generated automatically)
    public abstract Builder addMember(String member);
    public abstract Builder addSkill(String skill);
    
    // Multiple item adders (generated automatically)  
    public abstract Builder addAllMembers(Iterable<String> members);
    public abstract Builder addAllSkills(Iterable<String> skills);
    
    public abstract Team build();
  }
}

Usage:

Team team = Team.builder()
    .name("Backend Team")
    .addMember("Alice")
    .addMember("Bob")
    .addAllMembers(Arrays.asList("Charlie", "Diana"))
    .addSkill("Java")
    .addAllSkills(Arrays.asList("Spring", "PostgreSQL"))
    .build();

toBuilder() Method

Generate a builder from an existing instance:

@AutoValue
public abstract class Person {
  public abstract String name();
  public abstract int age();
  public abstract Optional<String> email();
  
  // toBuilder method
  public abstract Builder toBuilder();
  
  public static Builder builder() {
    return new AutoValue_Person.Builder();
  }
  
  @AutoValue.Builder
  public abstract static class Builder {
    public abstract Builder name(String name);
    public abstract Builder age(int age);
    public abstract Builder email(String email);
    public abstract Person build();
  }
}

Usage:

Person original = Person.builder()
    .name("Alice")
    .age(30)
    .build();

Person updated = original.toBuilder()
    .age(31)
    .email("alice@example.com")
    .build();

Property Builders for Nested Objects

Build nested objects directly in the builder:

@AutoValue
public abstract class Address {
  public abstract String street();
  public abstract String city();
  
  public static Builder builder() {
    return new AutoValue_Address.Builder();
  }
  
  @AutoValue.Builder
  public abstract static class Builder {
    public abstract Builder street(String street);
    public abstract Builder city(String city);
    public abstract Address build();
  }
}

@AutoValue  
public abstract class Person {
  public abstract String name();
  public abstract Address address();
  
  public static Builder builder() {
    return new AutoValue_Person.Builder();
  }
  
  @AutoValue.Builder
  public abstract static class Builder {
    public abstract Builder name(String name);
    public abstract Builder address(Address address);
    
    // Property builder for nested object
    public abstract Address.Builder addressBuilder();
    
    public abstract Person build();
  }
}

Usage:

Person person = Person.builder()
    .name("Alice")
    .addressBuilder()
        .street("123 Main St")
        .city("Springfield")
        .and()  // Returns to parent builder
    .build();

// Or build separately
Address address = Address.builder()
    .street("456 Oak Ave")
    .city("Springfield")
    .build();
    
Person person2 = Person.builder()
    .name("Bob")
    .address(address)
    .build();

Builder Validation

Add validation to the build() method:

@AutoValue
public abstract class ValidatedPerson {
  public abstract String name();
  public abstract int age();
  public abstract String email();
  
  public static Builder builder() {
    return new AutoValue_ValidatedPerson.Builder();
  }
  
  @AutoValue.Builder
  public abstract static class Builder {
    public abstract Builder name(String name);
    public abstract Builder age(int age);
    public abstract Builder email(String email);
    
    abstract ValidatedPerson autoBuild(); // Package-private build method
    
    public ValidatedPerson build() {
      ValidatedPerson person = autoBuild();
      checkArgument(!person.name().isEmpty(), "Name cannot be empty");
      checkArgument(person.age() >= 0, "Age must be non-negative");
      checkArgument(person.email().contains("@"), "Invalid email format");
      return person;
    }
    
    private static void checkArgument(boolean condition, String message) {
      if (!condition) {
        throw new IllegalArgumentException(message);
      }
    }
  }
}

Optional Properties with Builders

Handle optional properties elegantly:

@AutoValue
public abstract class Product {
  public abstract String name();
  public abstract double price();
  public abstract Optional<String> description();
  public abstract Optional<String> category();
  
  public static Builder builder() {
    return new AutoValue_Product.Builder();
  }
  
  @AutoValue.Builder
  public abstract static class Builder {
    public abstract Builder name(String name);
    public abstract Builder price(double price);
    public abstract Builder description(String description);
    public abstract Builder category(String category);
    
    // Optional overloads for convenience
    public abstract Builder description(Optional<String> description);
    public abstract Builder category(Optional<String> category);
    
    public abstract Product build();
  }
}

Usage:

Product basic = Product.builder()
    .name("Widget")
    .price(19.99)
    .build(); // Optional fields will be empty

Product detailed = Product.builder()
    .name("Advanced Widget")
    .price(39.99)
    .description("A very advanced widget")
    .category("Electronics")
    .build();

Generic Builders

Builders work with generic types:

@AutoValue
public abstract class Container<T> {
  public abstract T value();
  public abstract String label();
  
  public static <T> Builder<T> builder() {
    return new AutoValue_Container.Builder<>();
  }
  
  @AutoValue.Builder
  public abstract static class Builder<T> {
    public abstract Builder<T> value(T value);
    public abstract Builder<T> label(String label);
    public abstract Container<T> build();
  }
}

Usage:

Container<String> stringContainer = Container.<String>builder()
    .value("Hello")
    .label("Greeting")
    .build();

Container<Integer> intContainer = Container.<Integer>builder()
    .value(42)
    .label("Answer")
    .build();

Builder Inheritance

Builders can be used with inheritance hierarchies:

public abstract class Animal {
  public abstract String name();
  public abstract int age();
}

@AutoValue
public abstract class Dog extends Animal {
  public abstract String breed();
  public abstract boolean trained();
  
  public static Builder builder() {
    return new AutoValue_Dog.Builder();
  }
  
  @AutoValue.Builder
  public abstract static class Builder {
    public abstract Builder name(String name);
    public abstract Builder age(int age);
    public abstract Builder breed(String breed);
    public abstract Builder trained(boolean trained);
    public abstract Dog build();
  }
}

Install with Tessl CLI

npx tessl i tessl/maven-com-google-auto-value--auto-value

docs

annotation-generation.md

builders.md

extensions.md

index.md

memoization.md

pretty-strings.md

serialization.md

standalone-builders.md

tagged-unions.md

value-classes.md

tile.json