aboutsummaryrefslogtreecommitdiff
path: root/value/README.md
blob: dcb5ec17f4ee8af456cf2db3211370d4bb001044 (plain)
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
# AutoValue

*Immutable value-type code generation for Java 1.6+* <br />
***Kevin Bourrillion, Éamonn McManus*** <br />
**Google, Inc.**

> "AutoValue may sound like a cheesy newspaper for unloading your jalopy on an
> unsuspecting stranger, but it's actually a great tool for eliminating the
> drudgery of writing mundane value classes in Java. It encapsulates much of the
> advice in Effective Java Chapter 2, and frees you to concentrate on the more
> interesting aspects of your program. The resulting program is likely to be
> shorter, clearer, and freer of bugs. Two thumbs up."
>
> -- *Joshua Bloch, author, Effective Java*

## Contents

<!-- generated with http://doctoc.herokuapp.com/ -->

-   [Background](#background)
-   [Design goals](#design-goals)
-   [How to use AutoValue](#how-to-use-autovalue)
    -   [In Example.java](#in-examplejava)
    -   [In ExampleTest.java](#in-exampletestjava)
    -   [In pom.xml](#in-pomxml)
    -   [What's going on here?](#whats-going-on-here)
    -   [Builders](#builders)
-   [Optional "features"](#optional-features)
    -   [Data hiding](#data-hiding)
    -   [Multiple creation paths](#multiple-creation-paths)
    -   [Default values with builders](#default-values-with-builders)
    -   [Nullability](#nullability)
    -   [JavaBeans-style prefixes are optional]
        (#javabeans-style-prefixes-are-optional)
    -   [Other preconditions or preprocessing]
        (#other-preconditions-or-preprocessing)
    -   [Custom implementations](#custom-implementations)
    -   [Nesting](#nesting)
    -   [Derived fields](#derived-fields)
    -   [Generics](#generics)
    -   [Converting back to a builder](#converting-back-to-a-builder)
    -   [Serialization](#serialization)
-   [Warnings](#warnings)
-   [Restrictions and non-features](#restrictions-and-non-features)
-   [Best practices](#best-practices)
-   [Alternatives](#alternatives)

## Background

Classes with value semantics are extremely common in Java. These are classes for
which object identity is irrelevant, and instances are considered
interchangeable based only on the equality of their field values. We will refer
to these classes as value types in this document.

To implement a value type safely and properly requires implementing `equals`,
`hashCode` and `toString` in a bloated, repetitive, formulaic yet error-prone
fashion. These methods are not especially time-consuming to write, especially
with the aid of IDE templates and a few Guava helpers, but they are a continual
burden to reviewers, editors and future readers. Their wide expanses of
boilerplate sharply decrease the signal-to-noise ratio of your code, and
constitute probably the single greatest violation of the DRY (Don't Repeat
Yourself) principle we are ever forced to commit.

AutoValue provides an easier way to create immutable value types, with less code
and less room for error, while **not restricting your freedom** to code any
aspect of your class just the way you want it.

## Design goals

AutoValue is the only solution to the value types problem in Java (that we are
aware of) having all of the following characteristics:

*   Usage is **API-invisible** (callers cannot become dependent on your choice
    to use it, or generally even tell the difference)
*   No required runtime dependencies
*   No performance penalty vs. hand-written code.
*   Virtually no limitations on what you can do with your class (private
    accessors, implementing interfaces, custom `hashCode()`, etc. See the
    "optional features" section.)
*   Minimal extralinguistic magic

## How to use AutoValue

The way to use AutoValue is a little surprising at first! Create your value type
as an abstract class, containing an abstract accessor method for each desired
field. This accessor can be any non-void, parameterless method. Add the
@AutoValue annotation to your class, and AutoValue will automatically generate
an implementing class.

### In `Example.java`

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

class Example {
  @AutoValue
  abstract static class Animal {
    static Animal create(String name, int numberOfLegs) {
      return new AutoValue_Example_Animal(name, numberOfLegs);
      // (or just AutoValue_Animal if this is not nested)
    }

    abstract String name();
    abstract int numberOfLegs();
  }
}
```

That's it! (In real life, some classes and methods would presumably be public
and have Javadoc.)

The central idea behind AutoValue is: if you can create an abstract class that
has one "obvious" reasonable implementation, a tool ought to be able to write
that implementation for you. And now it does.

### In `ExampleTest.java`

To a consumer, this looks and functions like any other object. The simple test
below illustrates that behavior. Note that in real life, you would write tests
that actually **do something interesting** with the object, instead of just
checking field values going in and out.

```java
public void testAnimal() {
  Animal dog = Animal.create("dog", 4);
  assertEquals("dog", dog.name());
  assertEquals(4, dog.numberOfLegs());

  // You really don't need to write tests like these; just illustrating.

  assertTrue(Animal.create("dog", 4).equals(dog));
  assertFalse(Animal.create("cat", 4).equals(dog));
  assertFalse(Animal.create("dog", 2).equals(dog));

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


### In `pom.xml`

For Maven users, add the following to your Maven configuration:

```xml
<dependency>
  <groupId>com.google.auto.value</groupId>
  <artifactId>auto-value</artifactId>
  <version>1.1</version>
  <scope>provided</scope>
</dependency>
```

### What's going on here?

AutoValue runs as a standard annotation processor in javac. It generates source
code, in your package, for a *package-private* implementation class called
**`AutoValue_Example_Animal`**. The generated class contains a field for each
abstract accessor method, and the generated constructor sets these fields. It
implements the accessor methods to simply return those references/values. It
implements equals to compare these values in the standard fashion, and
implements an appropriate corresponding `hashCode`. It implements `toString` to
return an unspecified string representation of the class.

Consumers of your value type don't need to know any of this. They just invoke
your provided factory method and get a well-behaved instance back.

### Builders

*(since 1.1)*

You may prefer to construct some objects through _builders_. If there is a
nested interface or abstract class that is annotated with `@AutoValue.Builder`,
then AutoValue will implement it to make it a builder class. The
`@AutoValue.Builder` interface or class is conventionally called `Builder`. It
must have method for every property to set the value of the property, and a
build method. Here is the example above written using builders.

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

class Example {
  @AutoValue
  abstract static class Animal {
    static Builder builder() {
      return new AutoValue_Example_Animal.Builder();
    }

    abstract String name();
    abstract int numberOfLegs();

    @AutoValue.Builder
    abstract static class Builder {
      abstract Builder name(String s);
      abstract Builder numberOfLegs(int n);
      abstract Animal build();
    }
  }
}
```

Now client code can look something like this:

```java
Animal dog = Animal.builder().name("dog").numberOfLegs(4).build();
```

## Optional "features"

Many of the following are not even features of AutoValue itself, just features
of the Java language which (unlike some other solutions to the value types
problem) AutoValue doesn't get in the way of.

### Data hiding

Your accessors don't have to be public! They do have to be at least
package-private. The fields themselves cannot be directly accessed.

### Multiple creation paths

You can offer as many static creation methods as you need, named descriptively,
to cover different combinations of parameters. They do not need to be named
`create` as in the example.

### Default values with builders

Generated builders require every property to be set, except `@Nullable`
properties. If you want to define a default value for a property, set it in the
`builder()` method before returning. Here's how to define that animals have 4
legs by default:

```java
class Example {
  @AutoValue
  abstract static class Animal {
    static Builder builder() {
      return new AutoValue_Example_Animal.Builder()
          .numberOfLegs(4);
    }
    // ...remainder as before...
  }
}
```

### Nullability

By default, AutoValue inserts a not-null check for each non-primitive parameter
passed to the generated constructor. If your class has a property that is
allowed to be null, apply `@Nullable` to the corresponding accessor method and
factory parameter. This has two effects: AutoValue will skip the null check, and
generate null-friendly code for `equals` and `hashCode`. The `@Nullable`
annotation can be `javax.annotation.Nullable` or a `Nullable` annotation defined
in any other package.

### JavaBeans-style prefixes are optional

In the example above, we used the `name()` and `numberOfLegs()` methods to
define the properties of the object. If you prefer, you can use JavaBeans-style
method names, like `getName()` and `getNumberOfLegs()` to achieve the same
effect. The property names will still be `name` and `numberOfLegs`, for example
in the result of `toString()`. This applies only if every abstract method looks
like `getX()` or `boolean isX()` for some non-empty string X.

Similarly, in a builder you can use methods like `name(String s)` and
`numberOfLegs(int n)` or methods like `setName(String s)` and
`setNumberOfLegs(int n)`. Again, every abstract method must follow the same one
of the two conventions.

### Other preconditions or preprocessing

If you need to check preconditions or perform any other preparatory steps,
insert the code to do so into your static factory method before invoking the
generated constructor. Remember that null checks are already present in the
generated constructor.

When using builders, you can validate by implementing your own build() method
that calls the generated build method, conventionally called autoBuild(). You
can construct an object provisionally and inspect its properties before
returning it. Here's how our example might be validated:

```java
class Example {
  @AutoValue
  abstract static class Animal {
    ...
    @AutoValue.Builder
    abstract static class Builder {
      abstract Builder name(String s);
      abstract Builder numberOfLegs(int n);

      abstract Animal autoBuild();
      Animal build() {
        Animal animal = autoBuild();
        if (animal.numberOfLegs() < 0) {
          throw new IllegalStateException("Negative legs");
        }
        return animal;
      }
    }
  }
}
```

If the Builder class is public, typically `build()` will be too but
`autoBuild()` will be package-private.

Sometimes it may be more convenient to consult the value in the builder before
calling `autoBuild()`. If the `Builder` class has an abstract method with the
same name and type as one of the methods in the `@AutoValue` class, it will be
implemented to return the value set on the builder, or throw an exception if no
value has been set. Like `autoBuild()`, these getter methods will typically not
be public.

```java
class Example {
  @AutoValue
  abstract static class Animal {
    abstract String name();
    abstract int numberOfLegs();

    ...

    @AutoValue.Builder
    abstract static class Builder {
      abstract Builder name(String s);
      abstract Builder numberOfLegs(int n);
      abstract int numberOfLegs();

      abstract Animal autoBuild();
      Animal build() {
        if (numberOfLegs() < 0) {
          throw new IllegalStateException("Negative legs");
        }
        return autoBuild();
      }
    }
  }
}
```

### Custom implementations

Don't like the `equals`, `hashCode` or `toString` method AutoValue generates?
You can underride it! Just write your own, directly in your abstract class;
AutoValue will see this and skip generating its own.

### Nesting

Your hand-written abstract value type can be nested at any level. The generated
implementation class is named `AutoValue_` plus each component of the class
named separated by underscores. For example, for the abstract class
`Foo.Bar.Qux`, the generated implementation class is `AutoValue_Foo_Bar_Qux`, in
the same package.

### Derived fields

If a field exists to cache a derived value, and should be ignored in `equals`,
`hashCode` and `toString`, define it directly in your class instead of providing
an abstract accessor for it. AutoValue will know nothing of it.

You may have fields you wish to ignore in equals for other reasons. We're sorry:
AutoValue doesn't work for these cases, since there's no way to pass the extra
parameter "through" the generated class constructor.

### Generics

An `@AutoValue` class can have type parameters, as illustrated in these
examples:

```java
@AutoValue
abstract class MapEntry<K extends Comparable<K>, V> implements Map.Entry<K, V> {
  static <K extends Comparable<K>, V> MapEntry<K, V> create(K key, V value) {
    return new AutoValue_MapEntry<K, V>(key, value);
  }
  ...
}
```

or

```java
@AutoValue
abstract class MapEntry<K extends Comparable<K>, V> implements Map.Entry<K, V> {
  static <K extends Comparable<K>, V> Builder<K, V> builder() {
    return new AutoValue_MapEntry.Builder<K, V>();
  }

  abstract static class Builder<K extends Comparable<K>, V> {
    abstract Builder setKey(K key);
    abstract Builder setValue(V value);
    abstract MapEntry<K, V> build();
  }
  ...
}
```

### Converting back to a builder

An `@AutoValue` class with a builder can optionally have an abstract method that
returns the builder type. It will be implemented by initializing the builder
with the values of the properties. This can be exposed directly to clients, or
used to implement "wither" methods that return a new object that is the same as
the original one except for one changed property. Here is an example:

```java
class Example {
  @AutoValue
  abstract static class Animal {
    static Builder builder() {
      return AutoValue_Example_Animal.Builder();
    }

    abstract Builder toBuilder();

    Animal withNumberOfLegs(int n) {
      return toBuilder().numberOfLegs(n).build();
    }
    // ...remainder as before...
  }
}
```

### Serialization

The generated class will be serializable if your abstract class implements
`Serializable`. It will be GWT-serializable if your abstract class is annotated
with `@GwtCompatible(serializable = true)` (any annotation with that name and
field will do, such as the one included in [Guava]).

(Ordinarily, abstract types should not be serializable, but in this case it's
harmless, since we truly expect no other implementations to ever exist.)

There is no way to mark individual fields as transient or customize the
serialization behavior.

[Guava]: https://github.com/google/guava

## Warnings

Use of AutoValue has one serious **negative consequence**: certain formerly safe
refactorings could now break your code, and be caught only by your tests.

If you are not using builders, you must ensure that parameters are passed to the
auto-generated constructor in the ***same order*** the corresponding accessor
methods are defined in the file. **Your tests must be sufficient** to catch any
field ordering problem. In most cases this should be the natural outcome from
testing whatever actual purpose this value type was created for! In other cases
a very simple test like the one shown above is enough.

We reserve the right to **change the `hashCode` implementation** at any time. Do
not depend on the order your objects appear in hash maps (use `ImmutableMap` or
`LinkedHashMap`!), and never persist these hash codes.


## Restrictions and non-features

*   Using AutoValue limits your public creation API to static factory methods,
    not constructors. See *Effective Java* Item 1 for several reasons this is
    usually a good idea anyway.

*   AutoValue does not and will not support creating *mutable* value types. (We
    may consider adding support for `withField`-style methods, which return a
    new immutable copy of the original instance with one field value changed.)

*   One `@AutoValue` class may not extend another. As explained in *Effective
    Java*, inheritance of value types simply doesn't work.

*   Object arrays are not and will not be supported, including multidimensional
    primitive array types. Use a `Collection` type instead, such as
    `ImmutableList`.

*   Your accessor methods may not be `private` -- but they may be
    package-private. The same is true for your `@AutoValue` class itself.

*   We don't generate `compareTo`, because we feel you need the expressiveness
    that [`ComparisonChain`] provides, and we can't beat it at its own game. If
    we find later that a large minority of AutoValue classes are implementing
    compareTo by the exact same formula, we will reconsider this feature.

*   AutoValue currently doesn't inspect the `new AutoValue_Foo` line to issue
    warnings on parameter order. (There are certain technical issues with doing
    so.) As stated above in Warnings, you had better have some test somewhere
    that will catch such problems. Or you can use builders to avoid having a
    parameter order at all.

*   It might seem convenient to use AutoValue to implement annotation
    interfaces, which frameworks such as [Guice] occasionally require. But in
    fact such interfaces must obey the contracts for `equals` and `hashCode`
    specified by java.lang.annotation.Annotation, and the implementations of
    those methods that AutoValue would generate do not. Instead, the
    com.google.auto.value package includes another annotation `@AutoAnnotation`
    specifically for this case. See its documentation for more details.

[`ComparisonChain`]: http://google.github.io/guava/releases/snapshot/api/docs/com/google/common/collect/ComparisonChain.html
[Guice]: https://github.com/google/guice/wiki/BindingAnnotations#user-content-binding-annotations-with-attributes

## Best practices

You should add a **package-private constructor** to your abstract class,
although we have omitted it for brevity in our examples. This accomplishes two
things: it prevents an undocumented public constructor (that no one can even
call) from appearing in your javadoc, and it prevents users outside your package
from creating their own subclasses (and potentially subverting your
immutability).

In fact, **you should virtually never need an alternative implementation of your
hand-written abstract class**, whether hand-written or generated by a mocking
framework. Your class can and should contain simple intrinsic behavior, but if
that behavior has enough complexity or enough dependencies that it actually
needs to be mocked or faked, split it into a separate type that is *not* a value
type. Otherwise it permits an instance with "real" behavior and one with
"mock/fake" behavior to be `equals`, which does not make sense. Keep your value
types straightforward.

Other code in the same package will be able to directly access the generated
class, *but should not*. It's best if each generated class has **one and only
one reference** from your source code. If you have multiple creation methods,
have them all call through to the same point, so there is still one call to the
generated file, and one place to insert preconditions, etc.

**Avoid mutable field types**, such as arrays, especially if you make your
accessor methods `public`. The generated accessors won't copy the field value on
its way out, so you'd be exposing your internal state. This doesn't mean your
factory method can't *accept* mutable types as input parameters. Example:

```java
@AutoValue
public abstract class ListExample {
  abstract ImmutableList<String> names();

  public static ListExample create(List<String> mutableNames) {
    return new AutoValue_ListExample(ImmutableList.copyOf(mutableNames));
  }
}
```

Finally, if you choose to provide an explicit `equals`, `hashCode` or `toString`
implementation, please make it **`final`**, so readers don't have to wonder
whether AutoValue is overriding it.

## Alternatives

This [slide presentation] walks through several competing solutions to this
problem and shows why we considered them insufficient.

[slide presentation]: https://docs.google.com/presentation/d/14u_h-lMn7f1rXE1nDiLX0azS3IkgjGl5uxp5jGJ75RE/edit