• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# How do I...
2
3
4This page answers common how-to questions that may come up when using AutoValue.
5You should read and understand the [Introduction](index.md) first.
6
7Questions specific to usage of the **builder option** are documented separately;
8for this, start by reading [AutoValue with builders](builders.md).
9
10## Contents
11
12How do I...
13
14*   ... [also generate a **builder** for my value class?](#builder)
15*   ... [use AutoValue with a **nested** class?](#nested)
16*   ... [use (or not use) JavaBeans-style name **prefixes**?](#beans)
17*   ... [use **nullable** properties?](#nullable)
18*   ... [perform other **validation**?](#validate)
19*   ... [use a property of a **mutable** type?](#mutable_property)
20*   ... [use a **custom** implementation of `equals`, etc.?](#custom)
21*   ... [have AutoValue implement a concrete or default method?](#concrete)
22*   ... [have multiple **`create`** methods, or name it/them
23    differently?](#create)
24*   ... [**ignore** certain properties in `equals`, etc.?](#ignore)
25*   ... [have AutoValue also implement abstract methods from my
26    **supertypes**?](#supertypes)
27*   ... [use AutoValue with a **generic** class?](#generic)
28*   ... [make my class Java- or GWT\-**serializable**?](#serialize)
29*   ... [use AutoValue to **implement** an **annotation** type?](#annotation)
30*   ... [also include **setter** (mutator) methods?](#setters)
31*   ... [also generate **`compareTo`**?](#compareTo)
32*   ... [use a **primitive array** for a property value?](#primitive_array)
33*   ... [use an **object array** for a property value?](#object_array)
34*   ... [have one `@AutoValue` class **extend** another?](#inherit)
35*   ... [keep my accessor methods **private**?](#private_accessors)
36*   ... [expose a **constructor**, not factory method, as my public creation
37    API?](#public_constructor)
38*   ... [use AutoValue on an **interface**, not abstract class?](#interface)
39*   ... [**memoize** ("cache") derived properties?](#memoize)
40*   ... [memoize the result of `hashCode` or
41    `toString`?](#memoize_hash_tostring)
42*   ... [make a class where only one of its properties is ever set?](#oneof)
43*   ... [copy annotations from a class/method to the implemented
44    class/method/field?](#copy_annotations)
45*   ... [create a **pretty string** representation?](#toprettystring)
46
47## <a name="builder"></a>... also generate a builder for my value class?
48
49Please see [AutoValue with builders](builders.md).
50
51## <a name="nested"></a>... use AutoValue with a nested class?
52
53AutoValue composes the generated class name in the form
54`AutoValue_`*`Outer_Middle_Inner`*.
55As many of these segments will be used in the generated name as required.
56Only the simple class name will appear in `toString` output.
57
58```java
59class Outer {
60  static class Middle {
61    @AutoValue
62    abstract static class Inner {
63      static Inner create(String foo) {
64        return new AutoValue_Outer_Middle_Inner(foo);
65      }
66      ...
67```
68
69## <a name="beans"></a>... use (or not use) JavaBeans-style name prefixes?
70
71Some developers prefer to name their accessors with a `get-` or `is-` prefix,
72but would prefer that only the "bare" property name be used in `toString` and
73for the generated constructor's parameter names.
74
75AutoValue will do exactly this, but only if you are using these prefixes
76*consistently*. In that case, it infers your intended property name by first
77stripping the `get-` or `is-` prefix, then adjusting the case of what remains as
78specified by
79[Introspector.decapitalize](http://docs.oracle.com/javase/8/docs/api/java/beans/Introspector.html#decapitalize).
80
81Note that, in keeping with the JavaBeans specification, the `is-` prefix is only
82allowed on `boolean`-returning methods. `get-` is allowed on any type of
83accessor.
84
85## <a name="nullable"></a>... use nullable properties?
86
87Ordinarily the generated constructor will reject any null values. If you want to
88accept null, simply apply any annotation named `@Nullable` to the appropriate
89accessor methods. This causes AutoValue to remove the null checks and generate
90null-friendly code for `equals`, `hashCode` and `toString`. Example:
91
92```java
93@AutoValue
94public abstract class Foo {
95  public static Foo create(@Nullable Bar bar) {
96    return new AutoValue_Foo(bar);
97  }
98
99  @Nullable abstract Bar bar();
100}
101```
102
103This example also shows annotating the corresponding `create` parameter with
104`@Nullable`. AutoValue does not actually require this annotation, only the one
105on the accessor, but we recommended it as useful documentation to your caller.
106Conversely, if `@Nullable` is only added to the parameter in `create` (or
107similarly the setter method of [AutoValue.Builder](builders)), but not the
108corresponding accessor method, it won't have any effect.
109
110## <a name="validate"></a>... perform other validation?
111
112Null checks are added automatically (as [above](#nullable)). For other types of
113precondition checks or pre-processing, just add them to your factory method:
114
115```java
116static MyType create(String first, String second) {
117  checkArgument(!first.isEmpty());
118  return new AutoValue_MyType(first, second.trim());
119}
120```
121
122## <a name="mutable_property"></a>... use a property of a mutable type?
123
124AutoValue classes are meant and expected to be immutable. But sometimes you
125would want to take a mutable type and use it as a property. In these cases:
126
127First, check if the mutable type has a corresponding immutable cousin. For
128example, the types `List<String>` and `String[]` have the immutable counterpart
129`ImmutableList<String>` in [Guava](http://github.com/google/guava). If so, use
130the immutable type for your property, and only accept the mutable type during
131construction:
132
133```java
134@AutoValue
135public abstract class ListExample {
136  public static ListExample create(String[] mutableNames) {
137    return new AutoValue_ListExample(ImmutableList.copyOf(mutableNames));
138  }
139
140  public abstract ImmutableList<String> names();
141}
142```
143
144Note: this is a perfectly sensible practice, not an ugly workaround!
145
146If there is no suitable immutable type to use, you'll need to proceed with
147caution. Your static factory method should pass a *clone* of the passed object
148to the generated constructor. Your accessor method should document a very loud
149warning never to mutate the object returned.
150
151```java
152@AutoValue
153public abstract class MutableExample {
154  public static MutableExample create(MutablePropertyType ouch) {
155    // Replace `MutablePropertyType.copyOf()` below with the right copying code for this type
156    return new AutoValue_MutableExample(MutablePropertyType.copyOf(ouch));
157  }
158
159  /**
160   * Returns the ouch associated with this object; <b>do not mutate</b> the
161   * returned object.
162   */
163  public abstract MutablePropertyType ouch();
164}
165```
166
167Warning: this is an ugly workaround, not a perfectly sensible practice! Callers
168can trivially break the invariants of the immutable class by mutating the
169accessor's return value. An example where something can go wrong: AutoValue
170objects can be used as keys in Maps.
171
172## <a name="custom"></a>... use a custom implementation of `equals`, etc.?
173
174Simply write your custom implementation; AutoValue will notice this and will
175skip generating its own. Your hand-written logic will thus be inherited on the
176concrete implementation class. We call this *underriding* the method.
177
178Remember when doing this that you are losing AutoValue's protections. Be careful
179to follow the basic rules of hash codes: equal objects must have equal hash
180codes *always*, and equal hash codes should imply equal objects *almost always*.
181You should now test your class more thoroughly, ideally using
182[`EqualsTester`](http://static.javadoc.io/com.google.guava/guava-testlib/19.0/com/google/common/testing/EqualsTester.html)
183from [guava-testlib](http://github.com/google/guava).
184
185Best practice: mark your underriding methods `final` to make it clear to future
186readers that these methods aren't overridden by AutoValue.
187
188## <a name="concrete"></a>... have AutoValue implement a concrete or default method?
189
190If a parent class defines a concrete (non-abstract) method that you would like
191AutoValue to implement, you can *redeclare* it as abstract. This applies to
192`Object` methods like `toString()`, but also to property methods that you would
193like to have AutoValue implement. It also applies to default methods in
194interfaces.
195
196```java
197@AutoValue
198class PleaseOverrideExample extends SuperclassThatDefinesToString {
199  ...
200
201  // cause AutoValue to generate this even though the superclass has it
202  @Override public abstract String toString();
203}
204```
205
206```java
207@AutoValue
208class PleaseReimplementDefaultMethod implements InterfaceWithDefaultMethod {
209  ...
210
211  // cause AutoValue to implement this even though the interface has a default
212  // implementation
213  @Override public abstract int numberOfLegs();
214}
215```
216
217## <a name="create"></a>... have multiple `create` methods, or name it/them differently?
218
219Just do it! AutoValue doesn't actually care. This
220[best practice item](practices.md#one_reference) may be relevant.
221
222## <a name="ignore"></a>... ignore certain properties in `equals`, etc.?
223
224Suppose your value class has an extra field that shouldn't be included in
225`equals` or `hashCode` computations.
226
227If this is because it is a derived value based on other properties, see [How do
228I memoize derived properties?](#memoize).
229
230Otherwise, first make certain that you really want to do this. It is often, but
231not always, a mistake. Remember that libraries will treat two equal instances as
232absolutely *interchangeable* with each other. Whatever information is present in
233this extra field could essentially "disappear" when you aren't expecting it, for
234example when your value is stored and retrieved from certain collections.
235
236If you're sure, here is how to do it:
237
238```java
239@AutoValue
240abstract class IgnoreExample {
241  static IgnoreExample create(String normalProperty, String ignoredProperty) {
242    IgnoreExample ie = new AutoValue_IgnoreExample(normalProperty);
243    ie.ignoredProperty.set(ignoredProperty);
244    return ie;
245  }
246
247  abstract String normalProperty();
248
249  private final AtomicReference<String> ignoredProperty = new AtomicReference<>();
250
251  final String ignoredProperty() {
252    return ignoredProperty.get();
253  }
254}
255```
256
257Note that this means the field is also ignored by `toString`; to AutoValue
258it simply doesn't exist.
259
260Note that we use `AtomicReference<String>` to ensure that other threads will
261correctly see the value that was written. You could also make the field
262`volatile`, or use `synchronized` (`synchronized (ie)` around the assignment and
263`synchronized` on the `ignoredProperty()` method).
264
265## <a name="supertypes"></a>... have AutoValue also implement abstract methods from my supertypes?
266
267AutoValue will recognize every abstract accessor method whether it is defined
268directly in your own hand-written class or in a supertype.
269
270These abstract methods can come from more than one place, for example from an
271interface and from the superclass. It may not then be obvious what order they
272are in, even though you need to know this order if you want to call the
273generated `AutoValue_Foo` constructor. You might find it clearer to use a
274[builder](builders.md) instead. But the order is deterministic: within a class
275or interface, methods are in the order they appear in the source code; methods
276in ancestors come before methods in descendants; methods in interfaces come
277before methods in classes; and in a class or interface that has more than one
278superinterface, the interfaces are in the order of their appearance in
279`implements` or `extends`.
280
281## <a name="generic"></a>... use AutoValue with a generic class?
282
283There's nothing to it: just add type parameters to your class and to your call
284to the generated constructor.
285
286## <a name="serialize"></a>... make my class Java- or GWT\-serializable?
287
288Just add `implements Serializable` or the `@GwtCompatible(serializable = true)`
289annotation (respectively) to your hand-written class; it (as well as any
290`serialVersionUID`) will be duplicated on the generated class, and you'll be
291good to go.
292
293## <a name="annotation"></a>... use AutoValue to implement an annotation type?
294
295Most users should never have the need to programmatically create "fake"
296annotation instances. But if you do, using `@AutoValue` in the usual way will
297fail because the `Annotation.hashCode` specification is incompatible with
298AutoValue's behavior.
299
300However, we've got you covered anyway! Suppose this annotation definition:
301
302```java
303public @interface Named {
304  String value();
305}
306```
307
308All you need is this:
309
310```java
311public class Names {
312  @AutoAnnotation public static Named named(String value) {
313    return new AutoAnnotation_Names_named(value);
314  }
315}
316```
317
318For more details, see the [`AutoAnnotation`
319javadoc](http://github.com/google/auto/blob/master/value/src/main/java/com/google/auto/value/AutoAnnotation.java#L24).
320
321## <a name="setters"></a>... also include setter (mutator) methods?
322
323You can't; AutoValue only generates immutable value classes.
324
325Note that giving value semantics to a mutable type is widely considered a
326questionable practice in the first place. Equal instances of a value class are
327treated as *interchangeable*, but they can't truly be interchangeable if one
328might be mutated and the other not.
329
330## <a name="compareTo"></a>... also generate `compareTo`?
331
332AutoValue intentionally does not provide this feature. It is better for you to
333roll your own comparison logic using the new methods added to
334[`Comparator`](https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html)
335in Java 8, or
336[`ComparisonChain`](https://guava.dev/releases/snapshot/api/docs/com/google/common/collect/ComparisonChain.html)
337from [Guava](http://github.com/google/guava).
338
339Since these mechanisms are easy to use, require very little code, and give you
340the flexibility you need, there's really no way for AutoValue to improve on
341them!
342
343## <a name="primitive_array"></a>... use a primitive array for a property value?
344
345Go right ahead! AutoValue will generate code that acts on the *values* stored
346the array, not the object identity of the array itself, which is (with virtual
347certainty) what you want. Heed the warnings given above about [mutable
348properties](#mutable_property).
349
350## <a name="object_array"></a>... use an object array for a property value?
351
352This is not allowed. Object arrays are very badly-behaved and unlike primitive
353arrays, they can be replaced with a proper `List` implementation for very little
354added cost.
355
356If it's important to accept an object array at construction time, refer to the
357*first* example shown [here](#mutable_property).
358
359## <a name="inherit"></a>... have one `@AutoValue` class extend another?
360
361This ability is intentionally not supported, because there is no way to do it
362correctly. See *Effective Java, 2nd Edition* Item 8: "Obey the general contract
363when overriding equals".
364
365## <a name="private_accessors"></a>... keep my accessor methods private?
366
367We're sorry. This is one of the rare and unfortunate restrictions AutoValue's
368approach places on your API. Your accessor methods don't have to be *public*,
369but they must be at least package-visible.
370
371## <a name="public_constructor"></a>... expose a constructor, not factory method, as my public creation API?
372
373We're sorry. This is one of the rare restrictions AutoValue's approach places on
374your API. However, note that static factory methods are recommended over public
375constructors by *Effective Java*, Item 1.
376
377## <a name="interface"></a>... use AutoValue on an interface, not abstract class?
378
379AutoValue classes can certainly implement an interface, however an interface may
380not be used in lieu of an abstract class. The only advantage of interfaces we're
381aware of is that you can omit `public abstract` from the methods. That's not
382much. On the other hand, you would lose the immutability guarantee, and you'd
383also invite more of the kind of bad behavior described in
384[this best-practices item](practices.md#simple). On balance, we don't think it's
385worth it.
386
387## <a name="memoize"></a>... memoize ("cache") derived properties?
388
389Sometimes your class has properties that are derived from the ones that
390AutoValue implements. You'd typically implement them with a concrete method that
391uses the other properties:
392
393```java
394@AutoValue
395abstract class Foo {
396  abstract Bar barProperty();
397
398  String derivedProperty() {
399    return someFunctionOf(barProperty());
400  }
401}
402```
403
404But what if `someFunctionOf(Bar)` is expensive? You'd like to calculate it only
405one time, then cache and reuse that value for all future calls. Normally,
406thread-safe lazy initialization involves a lot of tricky boilerplate.
407
408Instead, just write the derived-property accessor method as above, and
409annotate it with [`@Memoized`]. Then AutoValue will override that method to
410return a stored value after the first call:
411
412```java
413@AutoValue
414abstract class Foo {
415  abstract Bar barProperty();
416
417  @Memoized
418  String derivedProperty() {
419    return someFunctionOf(barProperty());
420  }
421}
422```
423
424Then your method will be called at most once, even if multiple threads attempt
425to access the property concurrently.
426
427The annotated method must have the usual form of an accessor method, and may not
428be `abstract`, `final`, or `private`.
429
430The stored value will not be used in the implementation of `equals`, `hashCode`,
431or `toString`.
432
433If a `@Memoized` method is also annotated with `@Nullable`, then `null` values
434will be stored; if not, then the overriding method throws `NullPointerException`
435when the annotated method returns `null`.
436
437[`@Memoized`]: https://github.com/google/auto/blob/master/value/src/main/java/com/google/auto/value/extension/memoized/Memoized.java
438
439## <a name="memoize_hash_tostring"></a>... memoize the result of `hashCode` or `toString`?
440
441You can also make your class remember and reuse the result of `hashCode`,
442`toString`, or both, like this:
443
444```java
445@AutoValue
446abstract class Foo {
447  abstract Bar barProperty();
448
449  @Memoized
450  @Override
451  public abstract int hashCode();
452
453  @Memoized
454  @Override
455  public abstract String toString();
456}
457```
458
459## <a name="oneof"></a>... make a class where only one of its properties is ever set?
460
461Often, the best way to do this is using inheritance. Although one
462`@AutoValue` class can't inherit from another, two `@AutoValue` classes can
463inherit from a common parent.
464
465```java
466public abstract class StringOrInteger {
467  public abstract String representation();
468
469  public static StringOrInteger ofString(String s) {
470    return new AutoValue_StringOrInteger_StringValue(s);
471  }
472
473  public static StringOrInteger ofInteger(int i) {
474    return new AutoValue_StringOrInteger_IntegerValue(i);
475  }
476
477  @AutoValue
478  abstract static class StringValue extends StringOrInteger {
479    abstract String string();
480
481    @Override
482    public String representation() {
483      return '"' + string() + '"';
484    }
485  }
486
487  @AutoValue
488  abstract static class IntegerValue extends StringOrInteger {
489    abstract int integer();
490
491    @Override
492    public String representation() {
493      return Integer.toString(integer());
494    }
495  }
496}
497```
498
499So any `StringOrInteger` instance is actually either a `StringValue` or an
500`IntegerValue`. Clients only care about the `representation()` method, so they
501don't need to know which it is.
502
503But if clients of your class may want to take different actions depending on
504which property is set, there is an alternative to `@AutoValue` called
505`@AutoOneOf`. This effectively creates a
506[*tagged union*](https://en.wikipedia.org/wiki/Tagged_union).
507Here is `StringOrInteger` written using `@AutoOneOf`, with the
508`representation()` method moved to a separate client class:
509
510```java
511@AutoOneOf(StringOrInteger.Kind.class)
512public abstract class StringOrInteger {
513  public enum Kind {STRING, INTEGER}
514  public abstract Kind getKind();
515
516  public abstract String string();
517
518  public abstract int integer();
519
520  public static StringOrInteger ofString(String s) {
521    return AutoOneOf_StringOrInteger.string(s);
522  }
523
524  public static StringOrInteger ofInteger(int i) {
525    return AutoOneOf_StringOrInteger.integer(i);
526  }
527}
528
529public class Client {
530  public String representation(StringOrInteger stringOrInteger) {
531    switch (stringOrInteger.getKind()) {
532      case STRING:
533        return '"' + stringOrInteger.string() + '"';
534      case INTEGER:
535        return Integer.toString(stringOrInteger.integer());
536    }
537    throw new AssertionError(stringOrInteger.getKind());
538  }
539}
540```
541
542Switching on an enum like this can lead to more robust code than using
543`instanceof` checks, especially if a tool like [Error
544Prone](https://errorprone.info/bugpattern/MissingCasesInEnumSwitch) can alert you
545if you add a new variant without updating all your switches. (On the other hand,
546if nothing outside your class references `getKind()`, you should consider if a
547solution using inheritance might be better.)
548
549There must be an enum such as `Kind`, though it doesn't have to be called `Kind`
550and it doesn't have to be nested inside the `@AutoOneOf` class. There must be an
551abstract method returning the enum, though it doesn't have to be called
552`getKind()`. For every value of the enum, there must be an abstract method with
553the same name (ignoring case and underscores). An `@AutoOneOf` class called
554`Foo` will then get a generated class called `AutoOneOf_Foo` that has a static
555factory method for each property, with the same name. In the example, the
556`STRING` value in the enum corresponds to the `string()` property and to the
557`AutoOneOf_StringOrInteger.string` factory method.
558
559Properties in an `@AutoOneOf` class can be `void` to indicate that the
560corresponding variant has no data. In that case, the factory method for that
561variant has no parameters:
562
563```java
564@AutoOneOf(Transform.Kind.class)
565public abstract class Transform {
566  public enum Kind {NONE, CIRCLE_CROP, BLUR}
567  public abstract Kind getKind();
568
569  abstract void none();
570
571  abstract void circleCrop();
572
573  public abstract BlurTransformParameters blur();
574
575  public static Transform ofNone() {
576    return AutoOneOf_Transform.none();
577  }
578
579  public static Transform ofCircleCrop() {
580    return AutoOneOf_Transform.circleCrop();
581  }
582
583  public static Transform ofBlur(BlurTransformParmeters params) {
584    return AutoOneOf_Transform.blur(params);
585  }
586}
587```
588
589Here, the `NONE` and `CIRCLE_CROP` variants have no associated data but are
590distinct from each other. The `BLUR` variant does have data. The `none()`
591and `circleCrop()` methods are package-private; they must exist to configure
592`@AutoOneOf`, but calling them is not very useful. (It does nothing if the
593instance is of the correct variant, or throws an exception otherwise.)
594
595The `AutoOneOf_Transform.none()` and `AutoOneOf_Transform.circleCrop()` methods
596return the same instance every time they are called.
597
598If one of the `void` variants means "none", consider using an `Optional<Transform>` or
599a `@Nullable Transform` instead of that variant.
600
601Properties in an `@AutoOneOf` class cannot be null. Instead of a
602`StringOrInteger` with a `@Nullable String`, you probably want a
603`@Nullable StringOrInteger` or an `Optional<StringOrInteger>`, or an empty
604variant as just described.
605
606## <a name="copy_annotations"></a>... copy annotations from a class/method to the implemented class/method/field?
607
608### Copying to the generated class
609
610If you want to copy annotations from your `@AutoValue`-annotated class to the
611generated `AutoValue_...` implementation, annotate your class with
612[`@AutoValue.CopyAnnotations`].
613
614For example, if `Example.java` is:
615
616```java
617@AutoValue
618@AutoValue.CopyAnnotations
619@SuppressWarnings("Immutable") // justification ...
620abstract class Example {
621  // details ...
622}
623```
624
625Then `@AutoValue` will generate `AutoValue_Example.java`:
626
627```java
628@SuppressWarnings("Immutable")
629final class AutoValue_Example extends Example {
630  // implementation ...
631}
632```
633
634Applying `@AutoValue.CopyAnnotations` to an `@AutoValue.Builder` class like
635`Foo.Builder` similarly causes annotations on that class to be copied to the
636generated subclass `AutoValue_Foo.Builder`.
637
638### Copying to the generated method
639
640For historical reasons, annotations on methods of an `@AutoValue`-annotated
641class are copied to the generated implementation class's methods. However, if
642you want to exclude some annotations from being copied, you can use
643[`@AutoValue.CopyAnnotations`]'s `exclude` method to stop this behavior.
644
645### Copying to the generated field
646
647If you want to copy annotations from your `@AutoValue`-annotated class's methods
648to the generated fields in the `AutoValue_...` implementation, annotate your
649method with [`@AutoValue.CopyAnnotations`].
650
651For example, if `Example.java` is:
652
653```java
654@Immutable
655@AutoValue
656abstract class Example {
657  @CopyAnnotations
658  @SuppressWarnings("Immutable") // justification ...
659  abstract Object getObject();
660
661  // other details ...
662}
663```
664
665Then `@AutoValue` will generate `AutoValue_Example.java`:
666
667```java
668final class AutoValue_Example extends Example {
669  @SuppressWarnings("Immutable")
670  private final Object object;
671
672  @SuppressWarnings("Immutable")
673  @Override
674  Object getObject() {
675    return object;
676  }
677
678  // other details ...
679}
680```
681
682[`@AutoValue.CopyAnnotations`]: http://static.javadoc.io/com.google.auto.value/auto-value/1.6/com/google/auto/value/AutoValue.CopyAnnotations.html
683
684## <a name="toprettystring"></a>... create a pretty string representation?
685
686If you have a value class with a long `toString()` representation, annotate a
687method with [`@ToPrettyString`] and AutoValue will generate an implementation that
688returns a pretty String rendering of the instance. For example:
689
690```java
691@AutoValue
692abstract class Song {
693  abstract String lyrics();
694  abstract List<Artist> artists();
695
696  @ToPrettyString
697  abstract String toPrettyString();
698}
699```
700
701Below is a sample rendering of the result of calling `toPrettyString()`.
702
703```
704Song {
705  lyrics = I'm off the deep end, watch as I dive in
706    I'll never meet the ground
707    Crash through the surface, where they can't hurt us
708    We're far from the shallow now.,
709  artists = [
710    Artist {
711      name = Lady Gaga,
712    },
713    Artist {
714      name = Bradley Cooper,
715    }
716  ],
717}
718```
719
720`@ToPrettyString` can be used on the default `toString()` to override the
721default AutoValue-generated `toString()` implementation, or on another
722user-defined method.
723
724[`@ToPrettyString`]: https://github.com/google/auto/blob/master/value/src/main/java/com/google/auto/value/extension/toprettystring/ToPrettyString.java
725