0
# Builder Pattern
1
2
AutoValue can generate builder classes that provide a fluent API for constructing value objects, especially useful for classes with many properties or optional fields.
3
4
## Basic Builder
5
6
```java { .api }
7
@AutoValue
8
public abstract class Person {
9
public abstract String name();
10
public abstract int age();
11
public abstract Optional<String> email();
12
13
public static Builder builder() {
14
return new AutoValue_Person.Builder();
15
}
16
17
@AutoValue.Builder
18
public abstract static class Builder {
19
public abstract Builder name(String name);
20
public abstract Builder age(int age);
21
public abstract Builder email(String email);
22
public abstract Person build();
23
}
24
}
25
```
26
27
## Usage Example
28
29
```java
30
Person person = Person.builder()
31
.name("Alice")
32
.age(30)
33
.email("alice@example.com")
34
.build();
35
36
// Optional properties can be omitted
37
Person personWithoutEmail = Person.builder()
38
.name("Bob")
39
.age(25)
40
.build();
41
```
42
43
## Builder with Defaults
44
45
Set default values in the builder factory method:
46
47
```java { .api }
48
@AutoValue
49
public abstract class Configuration {
50
public abstract String host();
51
public abstract int port();
52
public abstract boolean ssl();
53
public abstract int timeoutMs();
54
55
public static Builder builder() {
56
return new AutoValue_Configuration.Builder()
57
.host("localhost")
58
.port(8080)
59
.ssl(false)
60
.timeoutMs(5000);
61
}
62
63
@AutoValue.Builder
64
public abstract static class Builder {
65
public abstract Builder host(String host);
66
public abstract Builder port(int port);
67
public abstract Builder ssl(boolean ssl);
68
public abstract Builder timeoutMs(int timeoutMs);
69
public abstract Configuration build();
70
}
71
}
72
```
73
74
Usage with defaults:
75
76
```java
77
Configuration defaultConfig = Configuration.builder().build();
78
// host=localhost, port=8080, ssl=false, timeoutMs=5000
79
80
Configuration customConfig = Configuration.builder()
81
.host("api.example.com")
82
.ssl(true)
83
.build();
84
// host=api.example.com, port=8080, ssl=true, timeoutMs=5000
85
```
86
87
## Builder with Collections
88
89
Builders provide convenience methods for adding to collections:
90
91
```java { .api }
92
@AutoValue
93
public abstract class Team {
94
public abstract String name();
95
public abstract ImmutableList<String> members();
96
public abstract ImmutableSet<String> skills();
97
98
public static Builder builder() {
99
return new AutoValue_Team.Builder();
100
}
101
102
@AutoValue.Builder
103
public abstract static class Builder {
104
public abstract Builder name(String name);
105
106
// Collection setters
107
public abstract Builder members(Iterable<String> members);
108
public abstract Builder skills(Iterable<String> skills);
109
110
// Individual item adders (generated automatically)
111
public abstract Builder addMember(String member);
112
public abstract Builder addSkill(String skill);
113
114
// Multiple item adders (generated automatically)
115
public abstract Builder addAllMembers(Iterable<String> members);
116
public abstract Builder addAllSkills(Iterable<String> skills);
117
118
public abstract Team build();
119
}
120
}
121
```
122
123
Usage:
124
125
```java
126
Team team = Team.builder()
127
.name("Backend Team")
128
.addMember("Alice")
129
.addMember("Bob")
130
.addAllMembers(Arrays.asList("Charlie", "Diana"))
131
.addSkill("Java")
132
.addAllSkills(Arrays.asList("Spring", "PostgreSQL"))
133
.build();
134
```
135
136
## toBuilder() Method
137
138
Generate a builder from an existing instance:
139
140
```java { .api }
141
@AutoValue
142
public abstract class Person {
143
public abstract String name();
144
public abstract int age();
145
public abstract Optional<String> email();
146
147
// toBuilder method
148
public abstract Builder toBuilder();
149
150
public static Builder builder() {
151
return new AutoValue_Person.Builder();
152
}
153
154
@AutoValue.Builder
155
public abstract static class Builder {
156
public abstract Builder name(String name);
157
public abstract Builder age(int age);
158
public abstract Builder email(String email);
159
public abstract Person build();
160
}
161
}
162
```
163
164
Usage:
165
166
```java
167
Person original = Person.builder()
168
.name("Alice")
169
.age(30)
170
.build();
171
172
Person updated = original.toBuilder()
173
.age(31)
174
.email("alice@example.com")
175
.build();
176
```
177
178
## Property Builders for Nested Objects
179
180
Build nested objects directly in the builder:
181
182
```java { .api }
183
@AutoValue
184
public abstract class Address {
185
public abstract String street();
186
public abstract String city();
187
188
public static Builder builder() {
189
return new AutoValue_Address.Builder();
190
}
191
192
@AutoValue.Builder
193
public abstract static class Builder {
194
public abstract Builder street(String street);
195
public abstract Builder city(String city);
196
public abstract Address build();
197
}
198
}
199
200
@AutoValue
201
public abstract class Person {
202
public abstract String name();
203
public abstract Address address();
204
205
public static Builder builder() {
206
return new AutoValue_Person.Builder();
207
}
208
209
@AutoValue.Builder
210
public abstract static class Builder {
211
public abstract Builder name(String name);
212
public abstract Builder address(Address address);
213
214
// Property builder for nested object
215
public abstract Address.Builder addressBuilder();
216
217
public abstract Person build();
218
}
219
}
220
```
221
222
Usage:
223
224
```java
225
Person person = Person.builder()
226
.name("Alice")
227
.addressBuilder()
228
.street("123 Main St")
229
.city("Springfield")
230
.and() // Returns to parent builder
231
.build();
232
233
// Or build separately
234
Address address = Address.builder()
235
.street("456 Oak Ave")
236
.city("Springfield")
237
.build();
238
239
Person person2 = Person.builder()
240
.name("Bob")
241
.address(address)
242
.build();
243
```
244
245
## Builder Validation
246
247
Add validation to the build() method:
248
249
```java { .api }
250
@AutoValue
251
public abstract class ValidatedPerson {
252
public abstract String name();
253
public abstract int age();
254
public abstract String email();
255
256
public static Builder builder() {
257
return new AutoValue_ValidatedPerson.Builder();
258
}
259
260
@AutoValue.Builder
261
public abstract static class Builder {
262
public abstract Builder name(String name);
263
public abstract Builder age(int age);
264
public abstract Builder email(String email);
265
266
abstract ValidatedPerson autoBuild(); // Package-private build method
267
268
public ValidatedPerson build() {
269
ValidatedPerson person = autoBuild();
270
checkArgument(!person.name().isEmpty(), "Name cannot be empty");
271
checkArgument(person.age() >= 0, "Age must be non-negative");
272
checkArgument(person.email().contains("@"), "Invalid email format");
273
return person;
274
}
275
276
private static void checkArgument(boolean condition, String message) {
277
if (!condition) {
278
throw new IllegalArgumentException(message);
279
}
280
}
281
}
282
}
283
```
284
285
## Optional Properties with Builders
286
287
Handle optional properties elegantly:
288
289
```java { .api }
290
@AutoValue
291
public abstract class Product {
292
public abstract String name();
293
public abstract double price();
294
public abstract Optional<String> description();
295
public abstract Optional<String> category();
296
297
public static Builder builder() {
298
return new AutoValue_Product.Builder();
299
}
300
301
@AutoValue.Builder
302
public abstract static class Builder {
303
public abstract Builder name(String name);
304
public abstract Builder price(double price);
305
public abstract Builder description(String description);
306
public abstract Builder category(String category);
307
308
// Optional overloads for convenience
309
public abstract Builder description(Optional<String> description);
310
public abstract Builder category(Optional<String> category);
311
312
public abstract Product build();
313
}
314
}
315
```
316
317
Usage:
318
319
```java
320
Product basic = Product.builder()
321
.name("Widget")
322
.price(19.99)
323
.build(); // Optional fields will be empty
324
325
Product detailed = Product.builder()
326
.name("Advanced Widget")
327
.price(39.99)
328
.description("A very advanced widget")
329
.category("Electronics")
330
.build();
331
```
332
333
## Generic Builders
334
335
Builders work with generic types:
336
337
```java { .api }
338
@AutoValue
339
public abstract class Container<T> {
340
public abstract T value();
341
public abstract String label();
342
343
public static <T> Builder<T> builder() {
344
return new AutoValue_Container.Builder<>();
345
}
346
347
@AutoValue.Builder
348
public abstract static class Builder<T> {
349
public abstract Builder<T> value(T value);
350
public abstract Builder<T> label(String label);
351
public abstract Container<T> build();
352
}
353
}
354
```
355
356
Usage:
357
358
```java
359
Container<String> stringContainer = Container.<String>builder()
360
.value("Hello")
361
.label("Greeting")
362
.build();
363
364
Container<Integer> intContainer = Container.<Integer>builder()
365
.value(42)
366
.label("Answer")
367
.build();
368
```
369
370
## Builder Inheritance
371
372
Builders can be used with inheritance hierarchies:
373
374
```java { .api }
375
public abstract class Animal {
376
public abstract String name();
377
public abstract int age();
378
}
379
380
@AutoValue
381
public abstract class Dog extends Animal {
382
public abstract String breed();
383
public abstract boolean trained();
384
385
public static Builder builder() {
386
return new AutoValue_Dog.Builder();
387
}
388
389
@AutoValue.Builder
390
public abstract static class Builder {
391
public abstract Builder name(String name);
392
public abstract Builder age(int age);
393
public abstract Builder breed(String breed);
394
public abstract Builder trained(boolean trained);
395
public abstract Dog build();
396
}
397
}
398
```