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 the 258private field 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 295Note: If you are writing your annotation in Kotlin, you don't need to use 296`@AutoAnnotation`, since Kotlin allows you to instantiate annotations directly. 297 298Most users should never have the need to programmatically create "fake" 299annotation instances. But if you do, using `@AutoValue` in the usual way will 300fail because the `Annotation.hashCode` specification is incompatible with 301AutoValue's behavior. 302 303However, we've got you covered anyway! Suppose this annotation definition: 304 305```java 306public @interface Named { 307 String value(); 308} 309``` 310 311All you need is this: 312 313```java 314public class Names { 315 @AutoAnnotation public static Named named(String value) { 316 return new AutoAnnotation_Names_named(value); 317 } 318} 319``` 320 321If your annotation has several elements, you may prefer to use `@AutoBuilder`: 322 323```java 324public @interface Named { 325 String value(); 326 int priority() default 0; 327 int size() default 0; 328} 329 330public class Names { 331 @AutoBuilder(ofClass = Named.class) 332 public interface NamedBuilder { 333 NamedBuilder value(String x); 334 NamedBuilder priority(int x); 335 NamedBuilder size(int x); 336 Named build(); 337 } 338 339 public static NamedBuilder namedBuilder() { 340 return new AutoBuilder_Names_namedBuilder(); 341 } 342 343 ... 344 Named named1 = namedBuilder().value("O'Cruiskeen").priority(17).size(23).build(); 345 Named named2 = namedBuilder().value("O'Cruiskeen").build(); 346 // priority and size get their default values 347 ... 348} 349``` 350 351For more details, see the [`AutoAnnotation` 352javadoc](http://github.com/google/auto/blob/main/value/src/main/java/com/google/auto/value/AutoAnnotation.java#L24). 353 354## <a name="setters"></a>... also include setter (mutator) methods? 355 356You can't; AutoValue only generates immutable value classes. 357 358Note that giving value semantics to a mutable type is widely considered a 359questionable practice in the first place. Equal instances of a value class are 360treated as *interchangeable*, but they can't truly be interchangeable if one 361might be mutated and the other not. 362 363## <a name="compareTo"></a>... also generate `compareTo`? 364 365AutoValue intentionally does not provide this feature. It is better for you to 366roll your own comparison logic using the new methods added to 367[`Comparator`](https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html) 368in Java 8, or 369[`ComparisonChain`](https://guava.dev/releases/snapshot/api/docs/com/google/common/collect/ComparisonChain.html) 370from [Guava](http://github.com/google/guava). 371 372Since these mechanisms are easy to use, require very little code, and give you 373the flexibility you need, there's really no way for AutoValue to improve on 374them! 375 376## <a name="primitive_array"></a>... use a primitive array for a property value? 377 378Go right ahead! AutoValue will generate code that acts on the *values* stored 379the array, not the object identity of the array itself, which is (with virtual 380certainty) what you want. Heed the warnings given above about [mutable 381properties](#mutable_property). 382 383## <a name="object_array"></a>... use an object array for a property value? 384 385This is not allowed. Object arrays are very badly-behaved and unlike primitive 386arrays, they can be replaced with a proper `List` implementation for very little 387added cost. 388 389If it's important to accept an object array at construction time, refer to the 390*first* example shown [here](#mutable_property). 391 392## <a name="inherit"></a>... have one `@AutoValue` class extend another? 393 394This ability is intentionally not supported, because there is no way to do it 395correctly. See *Effective Java, 2nd Edition* Item 8: "Obey the general contract 396when overriding equals". 397 398## <a name="private_accessors"></a>... keep my accessor methods private? 399 400We're sorry. This is one of the rare and unfortunate restrictions AutoValue's 401approach places on your API. Your accessor methods don't have to be *public*, 402but they must be at least package-visible. 403 404## <a name="public_constructor"></a>... expose a constructor, not factory method, as my public creation API? 405 406We're sorry. This is one of the rare restrictions AutoValue's approach places on 407your API. However, note that static factory methods are recommended over public 408constructors by *Effective Java*, Item 1. 409 410## <a name="interface"></a>... use AutoValue on an interface, not abstract class? 411 412AutoValue classes can certainly implement an interface, however an interface may 413not be used in lieu of an abstract class. The only advantage of interfaces we're 414aware of is that you can omit `public abstract` from the methods. That's not 415much. On the other hand, you would lose the immutability guarantee, and you'd 416also invite more of the kind of bad behavior described in 417[this best-practices item](practices.md#simple). On balance, we don't think it's 418worth it. 419 420## <a name="memoize"></a>... memoize ("cache") derived properties? 421 422Sometimes your class has properties that are derived from the ones that 423AutoValue implements. You'd typically implement them with a concrete method that 424uses the other properties: 425 426```java 427@AutoValue 428abstract class Foo { 429 abstract Bar barProperty(); 430 431 String derivedProperty() { 432 return someFunctionOf(barProperty()); 433 } 434} 435``` 436 437But what if `someFunctionOf(Bar)` is expensive? You'd like to calculate it only 438one time, then cache and reuse that value for all future calls. Normally, 439thread-safe lazy initialization involves a lot of tricky boilerplate. 440 441Instead, just write the derived-property accessor method as above, and 442annotate it with [`@Memoized`]. Then AutoValue will override that method to 443return a stored value after the first call: 444 445```java 446@AutoValue 447abstract class Foo { 448 abstract Bar barProperty(); 449 450 @Memoized 451 String derivedProperty() { 452 return someFunctionOf(barProperty()); 453 } 454} 455``` 456 457Then your method will be called at most once, even if multiple threads attempt 458to access the property concurrently. 459 460The annotated method must have the usual form of an accessor method, and may not 461be `abstract`, `final`, or `private`. 462 463The stored value will not be used in the implementation of `equals`, `hashCode`, 464or `toString`. 465 466If a `@Memoized` method is also annotated with `@Nullable`, then `null` values 467will be stored; if not, then the overriding method throws `NullPointerException` 468when the annotated method returns `null`. 469 470[`@Memoized`]: https://github.com/google/auto/blob/main/value/src/main/java/com/google/auto/value/extension/memoized/Memoized.java 471 472## <a name="memoize_hash_tostring"></a>... memoize the result of `hashCode` or `toString`? 473 474You can also make your class remember and reuse the result of `hashCode`, 475`toString`, or both, like this: 476 477```java 478@AutoValue 479abstract class Foo { 480 abstract Bar barProperty(); 481 482 @Memoized 483 @Override 484 public abstract int hashCode(); 485 486 @Memoized 487 @Override 488 public abstract String toString(); 489} 490``` 491 492## <a name="oneof"></a>... make a class where only one of its properties is ever set? 493 494Often, the best way to do this is using inheritance. Although one 495`@AutoValue` class can't inherit from another, two `@AutoValue` classes can 496inherit from a common parent. 497 498```java 499public abstract class StringOrInteger { 500 public abstract String representation(); 501 502 public static StringOrInteger ofString(String s) { 503 return new AutoValue_StringOrInteger_StringValue(s); 504 } 505 506 public static StringOrInteger ofInteger(int i) { 507 return new AutoValue_StringOrInteger_IntegerValue(i); 508 } 509 510 @AutoValue 511 abstract static class StringValue extends StringOrInteger { 512 abstract String string(); 513 514 @Override 515 public String representation() { 516 return '"' + string() + '"'; 517 } 518 } 519 520 @AutoValue 521 abstract static class IntegerValue extends StringOrInteger { 522 abstract int integer(); 523 524 @Override 525 public String representation() { 526 return Integer.toString(integer()); 527 } 528 } 529} 530``` 531 532So any `StringOrInteger` instance is actually either a `StringValue` or an 533`IntegerValue`. Clients only care about the `representation()` method, so they 534don't need to know which it is. 535 536But if clients of your class may want to take different actions depending on 537which property is set, there is an alternative to `@AutoValue` called 538`@AutoOneOf`. This effectively creates a 539[*tagged union*](https://en.wikipedia.org/wiki/Tagged_union). 540Here is `StringOrInteger` written using `@AutoOneOf`, with the 541`representation()` method moved to a separate client class: 542 543```java 544@AutoOneOf(StringOrInteger.Kind.class) 545public abstract class StringOrInteger { 546 public enum Kind {STRING, INTEGER} 547 public abstract Kind getKind(); 548 549 public abstract String string(); 550 551 public abstract int integer(); 552 553 public static StringOrInteger ofString(String s) { 554 return AutoOneOf_StringOrInteger.string(s); 555 } 556 557 public static StringOrInteger ofInteger(int i) { 558 return AutoOneOf_StringOrInteger.integer(i); 559 } 560} 561 562public class Client { 563 public String representation(StringOrInteger stringOrInteger) { 564 switch (stringOrInteger.getKind()) { 565 case STRING: 566 return '"' + stringOrInteger.string() + '"'; 567 case INTEGER: 568 return Integer.toString(stringOrInteger.integer()); 569 } 570 throw new AssertionError(stringOrInteger.getKind()); 571 } 572} 573``` 574 575Switching on an enum like this can lead to more robust code than using 576`instanceof` checks, especially if a tool like [Error 577Prone](https://errorprone.info/bugpattern/MissingCasesInEnumSwitch) can alert you 578if you add a new variant without updating all your switches. (On the other hand, 579if nothing outside your class references `getKind()`, you should consider if a 580solution using inheritance might be better.) 581 582There must be an enum such as `Kind`, though it doesn't have to be called `Kind` 583and it doesn't have to be nested inside the `@AutoOneOf` class. There must be an 584abstract method returning the enum, though it doesn't have to be called 585`getKind()`. For every value of the enum, there must be an abstract method with 586the same name (ignoring case and underscores). An `@AutoOneOf` class called 587`Foo` will then get a generated class called `AutoOneOf_Foo` that has a static 588factory method for each property, with the same name. In the example, the 589`STRING` value in the enum corresponds to the `string()` property and to the 590`AutoOneOf_StringOrInteger.string` factory method. 591 592Properties in an `@AutoOneOf` class can be `void` to indicate that the 593corresponding variant has no data. In that case, the factory method for that 594variant has no parameters: 595 596```java 597@AutoOneOf(Transform.Kind.class) 598public abstract class Transform { 599 public enum Kind {NONE, CIRCLE_CROP, BLUR} 600 public abstract Kind getKind(); 601 602 abstract void none(); 603 604 abstract void circleCrop(); 605 606 public abstract BlurTransformParameters blur(); 607 608 public static Transform ofNone() { 609 return AutoOneOf_Transform.none(); 610 } 611 612 public static Transform ofCircleCrop() { 613 return AutoOneOf_Transform.circleCrop(); 614 } 615 616 public static Transform ofBlur(BlurTransformParmeters params) { 617 return AutoOneOf_Transform.blur(params); 618 } 619} 620``` 621 622Here, the `NONE` and `CIRCLE_CROP` variants have no associated data but are 623distinct from each other. The `BLUR` variant does have data. The `none()` 624and `circleCrop()` methods are package-private; they must exist to configure 625`@AutoOneOf`, but calling them is not very useful. (It does nothing if the 626instance is of the correct variant, or throws an exception otherwise.) 627 628The `AutoOneOf_Transform.none()` and `AutoOneOf_Transform.circleCrop()` methods 629return the same instance every time they are called. 630 631If one of the `void` variants means "none", consider using an `Optional<Transform>` or 632a `@Nullable Transform` instead of that variant. 633 634Properties in an `@AutoOneOf` class cannot be null. Instead of a 635`StringOrInteger` with a `@Nullable String`, you probably want a 636`@Nullable StringOrInteger` or an `Optional<StringOrInteger>`, or an empty 637variant as just described. 638 639## <a name="copy_annotations"></a>... copy annotations from a class/method to the implemented class/method/field? 640 641### Copying to the generated class 642 643If you want to copy annotations from your `@AutoValue`-annotated class to the 644generated `AutoValue_...` implementation, annotate your class with 645[`@AutoValue.CopyAnnotations`]. 646 647For example, if `Example.java` is: 648 649```java 650@AutoValue 651@AutoValue.CopyAnnotations 652@SuppressWarnings("Immutable") // justification ... 653abstract class Example { 654 // details ... 655} 656``` 657 658Then `@AutoValue` will generate `AutoValue_Example.java`: 659 660```java 661@SuppressWarnings("Immutable") 662final class AutoValue_Example extends Example { 663 // implementation ... 664} 665``` 666 667Applying `@AutoValue.CopyAnnotations` to an `@AutoValue.Builder` class like 668`Foo.Builder` similarly causes annotations on that class to be copied to the 669generated subclass `AutoValue_Foo.Builder`. 670 671### Copying to the generated method 672 673For historical reasons, annotations on methods of an `@AutoValue`-annotated 674class are copied to the generated implementation class's methods. However, if 675you want to exclude some annotations from being copied, you can use 676[`@AutoValue.CopyAnnotations`]'s `exclude` method to stop this behavior. 677 678### Copying to the generated field 679 680If you want to copy annotations from your `@AutoValue`-annotated class's methods 681to the generated fields in the `AutoValue_...` implementation, annotate your 682method with [`@AutoValue.CopyAnnotations`]. 683 684For example, if `Example.java` is: 685 686```java 687@Immutable 688@AutoValue 689abstract class Example { 690 @CopyAnnotations 691 @SuppressWarnings("Immutable") // justification ... 692 abstract Object getObject(); 693 694 // other details ... 695} 696``` 697 698Then `@AutoValue` will generate `AutoValue_Example.java`: 699 700```java 701final class AutoValue_Example extends Example { 702 @SuppressWarnings("Immutable") 703 private final Object object; 704 705 @SuppressWarnings("Immutable") 706 @Override 707 Object getObject() { 708 return object; 709 } 710 711 // other details ... 712} 713``` 714 715[`@AutoValue.CopyAnnotations`]: http://static.javadoc.io/com.google.auto.value/auto-value/1.6/com/google/auto/value/AutoValue.CopyAnnotations.html 716 717## <a name="toprettystring"></a>... create a pretty string representation? 718 719If you have a value class with a long `toString()` representation, annotate a 720method with [`@ToPrettyString`] and AutoValue will generate an implementation that 721returns a pretty String rendering of the instance. For example: 722 723```java 724@AutoValue 725abstract class Song { 726 abstract String lyrics(); 727 abstract List<Artist> artists(); 728 729 @ToPrettyString 730 abstract String toPrettyString(); 731} 732``` 733 734Below is a sample rendering of the result of calling `toPrettyString()`. 735 736``` 737Song { 738 lyrics = I'm off the deep end, watch as I dive in 739 I'll never meet the ground 740 Crash through the surface, where they can't hurt us 741 We're far from the shallow now., 742 artists = [ 743 Artist { 744 name = Lady Gaga, 745 }, 746 Artist { 747 name = Bradley Cooper, 748 } 749 ], 750} 751``` 752 753`@ToPrettyString` can be used on the default `toString()` to override the 754default AutoValue-generated `toString()` implementation, or on another 755user-defined method. 756 757[`@ToPrettyString`]: https://github.com/google/auto/blob/main/value/src/main/java/com/google/auto/value/extension/toprettystring/ToPrettyString.java 758