File: builders.md

package info (click to toggle)
google-auto-service-java 1.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 3,136 kB
  • sloc: java: 36,551; xml: 1,498; sh: 34; makefile: 11
file content (106 lines) | stat: -rw-r--r-- 4,332 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# AutoValue with Builders


The [introduction](index.md) of this User Guide covers the basic usage of
AutoValue using a static factory method as your public creation API. But in many
circumstances (such as those laid out in *Effective Java, 2nd Edition* Item 2),
you may prefer to let your callers use a *builder* instead.

Fortunately, AutoValue can generate builder classes too! This page explains how.
Note that we recommend reading and understanding the basic usage shown in the
[introduction](index.md) first.

## How to use AutoValue with Builders <a name="howto"></a>

As explained in the introduction, the AutoValue concept is that **you write an
abstract value class, and AutoValue implements it**. Builder generation works in
the exact same way: you also create an abstract builder class, nesting it inside
your abstract value class, and AutoValue generates implementations for both.

### In `Animal.java` <a name="example_java"></a>

```java
import com.google.auto.value.AutoValue;

@AutoValue
abstract class Animal {
  abstract String name();
  abstract int numberOfLegs();

  static Builder builder() {
    return new AutoValue_Animal.Builder();
  }

  @AutoValue.Builder
  abstract static class Builder {
    abstract Builder setName(String value);
    abstract Builder setNumberOfLegs(int value);
    abstract Animal build();
  }
}
```

Note that in real life, some classes and methods would presumably be public and
have **Javadoc**. We're leaving these off in the User Guide only to keep the
examples clean and short.

### Usage <a name="usage"></a>

```java
public void testAnimal() {
  Animal dog = Animal.builder().setName("dog").setNumberOfLegs(4).build();
  assertEquals("dog", dog.name());
  assertEquals(4, dog.numberOfLegs());

  // You probably don't need to write assertions like these; just illustrating.
  assertTrue(
      Animal.builder().setName("dog").setNumberOfLegs(4).build().equals(dog));
  assertFalse(
      Animal.builder().setName("cat").setNumberOfLegs(4).build().equals(dog));
  assertFalse(
      Animal.builder().setName("dog").setNumberOfLegs(2).build().equals(dog));

  assertEquals("Animal{name=dog, numberOfLegs=4}", dog.toString());
}
```

### What does AutoValue generate? <a name="generated"></a>

For the `Animal` example shown above, here is [typical code AutoValue might
generate](generated-builder-example.md).

## Warnings <a name="warnings"></a>

Be sure to put the static `builder()` method directly in your value class (e.g.,
`Animal`) and not the nested abstract `Builder` class. That ensures that the
`Animal` class is always initialized before `Builder`. Otherwise you may be
exposing yourself to initialization-order problems.

## <a name="howto"></a>How do I...

*   ... [use (or not use) `set` **prefixes**?](builders-howto.md#beans)
*   ... [use different **names** besides
    `builder()`/`Builder`/`build()`?](builders-howto.md#build_names)
*   ... [specify a **default** value for a property?](builders-howto.md#default)
*   ... [initialize a builder to the same property values as an **existing**
    value instance](builders-howto.md#to_builder)
*   ... [include `with-` methods on my value class for creating slightly
    **altered** instances?](builders-howto.md#withers)
*   ... [**validate** property values?](builders-howto.md#validate)
*   ... [**normalize** (modify) a property value at `build`
    time?](builders-howto.md#normalize)
*   ... [expose **both** a builder and a factory
    method?](builders-howto.md#both)
*   ... [handle `Optional` properties?](builders-howto.md#optional)
*   ... [use a **collection**-valued property?](builders-howto.md#collection)
    *   ... [let my builder **accumulate** values for a collection-valued
        property (not require them all at once)?](builders-howto.md#accumulate)
    *   ... [accumulate values for a collection-valued property, without
        **"breaking the chain"**?](builders-howto.md#add)
    *   ... [offer **both** accumulation and set-at-once methods for the same
        collection-valued property?](builders-howto.md#collection_both)
*   ... [access nested builders while
    building?](builders-howto.md#nested_builders)
*   ... [create a "step builder"?](builders-howto.md#step)
*   ... [create a builder for something other than an
    `@AutoValue`?](builders-howto.md#autobuilder)