xref: /aosp_15_r20/external/auto/value/userguide/builders.md (revision 1c2bbba85eccddce6de79cbbf1645fda32e723f0)
1# AutoValue with Builders
2
3
4The [introduction](index.md) of this User Guide covers the basic usage of
5AutoValue using a static factory method as your public creation API. But in many
6circumstances (such as those laid out in *Effective Java, 2nd Edition* Item 2),
7you may prefer to let your callers use a *builder* instead.
8
9Fortunately, AutoValue can generate builder classes too! This page explains how.
10Note that we recommend reading and understanding the basic usage shown in the
11[introduction](index.md) first.
12
13## How to use AutoValue with Builders <a name="howto"></a>
14
15As explained in the introduction, the AutoValue concept is that **you write an
16abstract value class, and AutoValue implements it**. Builder generation works in
17the exact same way: you also create an abstract builder class, nesting it inside
18your abstract value class, and AutoValue generates implementations for both.
19
20### In `Animal.java` <a name="example_java"></a>
21
22```java
23import com.google.auto.value.AutoValue;
24
25@AutoValue
26abstract class Animal {
27  abstract String name();
28  abstract int numberOfLegs();
29
30  static Builder builder() {
31    // The naming here will be different if you are using a nested class
32    // e.g. `return new AutoValue_OuterClass_InnerClass.Builder();`
33    return new AutoValue_Animal.Builder();
34  }
35
36  @AutoValue.Builder
37  abstract static class Builder {
38    abstract Builder setName(String value);
39    abstract Builder setNumberOfLegs(int value);
40    abstract Animal build();
41  }
42}
43```
44
45Note that in real life, some classes and methods would presumably be public and
46have **Javadoc**. We're leaving these off in the User Guide only to keep the
47examples clean and short.
48
49### Usage <a name="usage"></a>
50
51```java
52public void testAnimal() {
53  Animal dog = Animal.builder().setName("dog").setNumberOfLegs(4).build();
54  assertEquals("dog", dog.name());
55  assertEquals(4, dog.numberOfLegs());
56
57  // You probably don't need to write assertions like these; just illustrating.
58  assertTrue(
59      Animal.builder().setName("dog").setNumberOfLegs(4).build().equals(dog));
60  assertFalse(
61      Animal.builder().setName("cat").setNumberOfLegs(4).build().equals(dog));
62  assertFalse(
63      Animal.builder().setName("dog").setNumberOfLegs(2).build().equals(dog));
64
65  assertEquals("Animal{name=dog, numberOfLegs=4}", dog.toString());
66}
67```
68
69### What does AutoValue generate? <a name="generated"></a>
70
71For the `Animal` example shown above, here is [typical code AutoValue might
72generate](generated-builder-example.md).
73
74## Warnings <a name="warnings"></a>
75
76Be sure to put the static `builder()` method directly in your value class (e.g.,
77`Animal`) and not the nested abstract `Builder` class. That ensures that the
78`Animal` class is always initialized before `Builder`. Otherwise you may be
79exposing yourself to initialization-order problems.
80
81## <a name="howto"></a>How do I...
82
83*   ... [use (or not use) `set` **prefixes**?](builders-howto.md#beans)
84*   ... [use different **names** besides
85    `builder()`/`Builder`/`build()`?](builders-howto.md#build_names)
86*   ... [specify a **default** value for a property?](builders-howto.md#default)
87*   ... [initialize a builder to the same property values as an **existing**
88    value instance](builders-howto.md#to_builder)
89*   ... [include `with-` methods on my value class for creating slightly
90    **altered** instances?](builders-howto.md#withers)
91*   ... [**validate** property values?](builders-howto.md#validate)
92*   ... [**normalize** (modify) a property value at `build`
93    time?](builders-howto.md#normalize)
94*   ... [expose **both** a builder and a factory
95    method?](builders-howto.md#both)
96*   ... [handle `Optional` properties?](builders-howto.md#optional)
97*   ... [use a **collection**-valued property?](builders-howto.md#collection)
98    *   ... [let my builder **accumulate** values for a collection-valued
99        property (not require them all at once)?](builders-howto.md#accumulate)
100    *   ... [accumulate values for a collection-valued property, without
101        **"breaking the chain"**?](builders-howto.md#add)
102    *   ... [offer **both** accumulation and set-at-once methods for the same
103        collection-valued property?](builders-howto.md#collection_both)
104*   ... [access nested builders while
105    building?](builders-howto.md#nested_builders)
106*   ... [create a "step builder"?](builders-howto.md#step)
107*   ... [create a builder for something other than an
108    `@AutoValue`?](builders-howto.md#autobuilder)
109*   ... [use a different build method for a
110    property?](builders-howto.md#build_method)
111