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