Home | History | Annotate | only in /external/javapoet
Up to higher level directory
NameDateSize
.buildscript/22-Oct-2020
.travis.yml22-Oct-20201.3K
Android.bp22-Oct-2020737
CHANGELOG.md22-Oct-202010.6K
checkstyle.xml22-Oct-20205.4K
CONTRIBUTING.md22-Oct-2020722
LICENSE22-Oct-202011.1K
LICENSE.txt22-Oct-202011.1K
METADATA22-Oct-2020329
MODULE_LICENSE_APACHE222-Oct-20200
NOTICE22-Oct-202011.1K
OWNERS22-Oct-202062
pom.xml22-Oct-20204.7K
README.md22-Oct-202025.8K
src/22-Oct-2020

README.md

      1 JavaPoet
      2 ========
      3 
      4 `JavaPoet` is a Java API for generating `.java` source files.
      5 
      6 Source file generation can be useful when doing things such as annotation processing or interacting
      7 with metadata files (e.g., database schemas, protocol formats). By generating code, you eliminate
      8 the need to write boilerplate while also keeping a single source of truth for the metadata.
      9 
     10 
     11 ### Example
     12 
     13 Here's a (boring) `HelloWorld` class:
     14 
     15 ```java
     16 package com.example.helloworld;
     17 
     18 public final class HelloWorld {
     19   public static void main(String[] args) {
     20     System.out.println("Hello, JavaPoet!");
     21   }
     22 }
     23 ```
     24 
     25 And this is the (exciting) code to generate it with JavaPoet:
     26 
     27 ```java
     28 MethodSpec main = MethodSpec.methodBuilder("main")
     29     .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
     30     .returns(void.class)
     31     .addParameter(String[].class, "args")
     32     .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")
     33     .build();
     34 
     35 TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
     36     .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
     37     .addMethod(main)
     38     .build();
     39 
     40 JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
     41     .build();
     42 
     43 javaFile.writeTo(System.out);
     44 ```
     45 
     46 To declare the main method, we've created a `MethodSpec` "main" configured with modifiers, return
     47 type, parameters and code statements. We add the main method to a `HelloWorld` class, and then add
     48 that to a `HelloWorld.java` file.
     49 
     50 In this case we write the file to `System.out`, but we could also get it as a string
     51 (`JavaFile.toString()`) or write it to the file system (`JavaFile.writeTo()`).
     52 
     53 The [Javadoc][javadoc] catalogs the complete JavaPoet API, which we explore below.
     54 
     55 ### Code & Control Flow
     56 
     57 Most of JavaPoet's API uses plain old immutable Java objects. There's also builders, method chaining
     58 and varargs to make the API friendly. JavaPoet offers models for classes & interfaces (`TypeSpec`),
     59 fields (`FieldSpec`), methods & constructors (`MethodSpec`), parameters (`ParameterSpec`) and
     60 annotations (`AnnotationSpec`).
     61 
     62 But the _body_ of methods and constructors is not modeled. There's no expression class, no
     63 statement class or syntax tree nodes. Instead, JavaPoet uses strings for code blocks:
     64 
     65 ```java
     66 MethodSpec main = MethodSpec.methodBuilder("main")
     67     .addCode(""
     68         + "int total = 0;\n"
     69         + "for (int i = 0; i < 10; i++) {\n"
     70         + "  total += i;\n"
     71         + "}\n")
     72     .build();
     73 ```
     74 
     75 Which generates this:
     76 
     77 ```java
     78 void main() {
     79   int total = 0;
     80   for (int i = 0; i < 10; i++) {
     81     total += i;
     82   }
     83 }
     84 ```
     85 
     86 The manual semicolons, line wrapping, and indentation are tedious and so JavaPoet offers APIs to
     87 make it easier. There's `addStatement()` which takes care of semicolons and newline, and
     88 `beginControlFlow()` + `endControlFlow()` which are used together for braces, newlines, and
     89 indentation:
     90 
     91 ```java
     92 MethodSpec main = MethodSpec.methodBuilder("main")
     93     .addStatement("int total = 0")
     94     .beginControlFlow("for (int i = 0; i < 10; i++)")
     95     .addStatement("total += i")
     96     .endControlFlow()
     97     .build();
     98 ```
     99 
    100 This example is lame because the generated code is constant! Suppose instead of just adding 0 to 10,
    101 we want to make the operation and range configurable. Here's a method that generates a method:
    102 
    103 ```java
    104 private MethodSpec computeRange(String name, int from, int to, String op) {
    105   return MethodSpec.methodBuilder(name)
    106       .returns(int.class)
    107       .addStatement("int result = 1")
    108       .beginControlFlow("for (int i = " + from + "; i < " + to + "; i++)")
    109       .addStatement("result = result " + op + " i")
    110       .endControlFlow()
    111       .addStatement("return result")
    112       .build();
    113 }
    114 ```
    115 
    116 And here's what we get when we call `computeRange("multiply10to20", 10, 20, "*")`:
    117 
    118 ```java
    119 int multiply10to20() {
    120   int result = 1;
    121   for (int i = 10; i < 20; i++) {
    122     result = result * i;
    123   }
    124   return result;
    125 }
    126 ```
    127 
    128 Methods generating methods! And since JavaPoet generates source instead of bytecode, you can
    129 read through it to make sure it's right.
    130 
    131 
    132 ### $L for Literals
    133 
    134 The string-concatenation in calls to `beginControlFlow()` and `addStatement` is distracting. Too
    135 many operators. To address this, JavaPoet offers a syntax inspired-by but incompatible-with
    136 [`String.format()`][formatter]. It accepts **`$L`** to emit a **literal** value in the output. This
    137 works just like `Formatter`'s `%s`:
    138 
    139 ```java
    140 private MethodSpec computeRange(String name, int from, int to, String op) {
    141   return MethodSpec.methodBuilder(name)
    142       .returns(int.class)
    143       .addStatement("int result = 0")
    144       .beginControlFlow("for (int i = $L; i < $L; i++)", from, to)
    145       .addStatement("result = result $L i", op)
    146       .endControlFlow()
    147       .addStatement("return result")
    148       .build();
    149 }
    150 ```
    151 
    152 Literals are emitted directly to the output code with no escaping. Arguments for literals may be
    153 strings, primitives, and a few JavaPoet types described below.
    154 
    155 ### $S for Strings
    156 
    157 When emitting code that includes string literals, we can use **`$S`** to emit a **string**, complete
    158 with wrapping quotation marks and escaping. Here's a program that emits 3 methods, each of which
    159 returns its own name:
    160 
    161 ```java
    162 public static void main(String[] args) throws Exception {
    163   TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
    164       .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
    165       .addMethod(whatsMyName("slimShady"))
    166       .addMethod(whatsMyName("eminem"))
    167       .addMethod(whatsMyName("marshallMathers"))
    168       .build();
    169 
    170   JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
    171       .build();
    172 
    173   javaFile.writeTo(System.out);
    174 }
    175 
    176 private static MethodSpec whatsMyName(String name) {
    177   return MethodSpec.methodBuilder(name)
    178       .returns(String.class)
    179       .addStatement("return $S", name)
    180       .build();
    181 }
    182 ```
    183 
    184 In this case, using `$S` gives us quotation marks:
    185 
    186 ```java
    187 public final class HelloWorld {
    188   String slimShady() {
    189     return "slimShady";
    190   }
    191 
    192   String eminem() {
    193     return "eminem";
    194   }
    195 
    196   String marshallMathers() {
    197     return "marshallMathers";
    198   }
    199 }
    200 ```
    201 
    202 ### $T for Types
    203 
    204 We Java programmers love our types: they make our code easier to understand. And JavaPoet is on
    205 board. It has rich built-in support for types, including automatic generation of `import`
    206 statements. Just use **`$T`** to reference **types**:
    207 
    208 ```java
    209 MethodSpec today = MethodSpec.methodBuilder("today")
    210     .returns(Date.class)
    211     .addStatement("return new $T()", Date.class)
    212     .build();
    213 
    214 TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
    215     .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
    216     .addMethod(today)
    217     .build();
    218 
    219 JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
    220     .build();
    221 
    222 javaFile.writeTo(System.out);
    223 ```
    224 
    225 That generates the following `.java` file, complete with the necessary `import`:
    226 
    227 ```java
    228 package com.example.helloworld;
    229 
    230 import java.util.Date;
    231 
    232 public final class HelloWorld {
    233   Date today() {
    234     return new Date();
    235   }
    236 }
    237 ```
    238 
    239 We passed `Date.class` to reference a class that just-so-happens to be available when we're
    240 generating code. This doesn't need to be the case. Here's a similar example, but this one
    241 references a class that doesn't exist (yet):
    242 
    243 ```java
    244 ClassName hoverboard = ClassName.get("com.mattel", "Hoverboard");
    245 
    246 MethodSpec today = MethodSpec.methodBuilder("tomorrow")
    247     .returns(hoverboard)
    248     .addStatement("return new $T()", hoverboard)
    249     .build();
    250 ```
    251 
    252 And that not-yet-existent class is imported as well:
    253 
    254 ```java
    255 package com.example.helloworld;
    256 
    257 import com.mattel.Hoverboard;
    258 
    259 public final class HelloWorld {
    260   Hoverboard tomorrow() {
    261     return new Hoverboard();
    262   }
    263 }
    264 ```
    265 
    266 The `ClassName` type is very important, and you'll need it frequently when you're using JavaPoet.
    267 It can identify any _declared_ class. Declared types are just the beginning of Java's rich type
    268 system: we also have arrays, parameterized types, wildcard types, and type variables. JavaPoet has
    269 classes for building each of these:
    270 
    271 ```java
    272 ClassName hoverboard = ClassName.get("com.mattel", "Hoverboard");
    273 ClassName list = ClassName.get("java.util", "List");
    274 ClassName arrayList = ClassName.get("java.util", "ArrayList");
    275 TypeName listOfHoverboards = ParameterizedTypeName.get(list, hoverboard);
    276 
    277 MethodSpec beyond = MethodSpec.methodBuilder("beyond")
    278     .returns(listOfHoverboards)
    279     .addStatement("$T result = new $T<>()", listOfHoverboards, arrayList)
    280     .addStatement("result.add(new $T())", hoverboard)
    281     .addStatement("result.add(new $T())", hoverboard)
    282     .addStatement("result.add(new $T())", hoverboard)
    283     .addStatement("return result")
    284     .build();
    285 ```
    286 
    287 JavaPoet will decompose each type and import its components where possible.
    288 
    289 ```java
    290 package com.example.helloworld;
    291 
    292 import com.mattel.Hoverboard;
    293 import java.util.ArrayList;
    294 import java.util.List;
    295 
    296 public final class HelloWorld {
    297   List<Hoverboard> beyond() {
    298     List<Hoverboard> result = new ArrayList<>();
    299     result.add(new Hoverboard());
    300     result.add(new Hoverboard());
    301     result.add(new Hoverboard());
    302     return result;
    303   }
    304 }
    305 ```
    306 
    307 #### Import static
    308 
    309 JavaPoet supports `import static`. It does it via explicitly collecting type member names. Let's
    310 enhance the previous example with some static sugar:
    311 
    312 ```java
    313 ...
    314 ClassName namedBoards = ClassName.get("com.mattel", "Hoverboard", "Boards");
    315 
    316 MethodSpec beyond = MethodSpec.methodBuilder("beyond")
    317     .returns(listOfHoverboards)
    318     .addStatement("$T result = new $T<>()", listOfHoverboards, arrayList)
    319     .addStatement("result.add($T.createNimbus(2000))", hoverboard)
    320     .addStatement("result.add($T.createNimbus(\"2001\"))", hoverboard)
    321     .addStatement("result.add($T.createNimbus($T.THUNDERBOLT))", hoverboard, namedBoards)
    322     .addStatement("$T.sort(result)", Collections.class)
    323     .addStatement("return result.isEmpty() ? $T.emptyList() : result", Collections.class)
    324     .build();
    325 
    326 TypeSpec hello = TypeSpec.classBuilder("HelloWorld")
    327     .addMethod(beyond)
    328     .build();
    329 
    330 JavaFile.builder("com.example.helloworld", hello)
    331     .addStaticImport(hoverboard, "createNimbus")
    332     .addStaticImport(namedBoards, "*")
    333     .addStaticImport(Collections.class, "*")
    334     .build();
    335 ```
    336 
    337 JavaPoet will first add your `import static` block to the file as configured, match and mangle
    338 all calls accordingly and also import all other types as needed.
    339 
    340 ```java
    341 package com.example.helloworld;
    342 
    343 import static com.mattel.Hoverboard.Boards.*;
    344 import static com.mattel.Hoverboard.createNimbus;
    345 import static java.util.Collections.*;
    346 
    347 import com.mattel.Hoverboard;
    348 import java.util.ArrayList;
    349 import java.util.List;
    350 
    351 class HelloWorld {
    352   List<Hoverboard> beyond() {
    353     List<Hoverboard> result = new ArrayList<>();
    354     result.add(createNimbus(2000));
    355     result.add(createNimbus("2001"));
    356     result.add(createNimbus(THUNDERBOLT));
    357     sort(result);
    358     return result.isEmpty() ? emptyList() : result;
    359   }
    360 }
    361 ```
    362 
    363 ### $N for Names
    364 
    365 Generated code is often self-referential. Use **`$N`** to refer to another generated declaration by
    366 its name. Here's a method that calls another:
    367 
    368 ```java
    369 public String byteToHex(int b) {
    370   char[] result = new char[2];
    371   result[0] = hexDigit((b >>> 4) & 0xf);
    372   result[1] = hexDigit(b & 0xf);
    373   return new String(result);
    374 }
    375 
    376 public char hexDigit(int i) {
    377   return (char) (i < 10 ? i + '0' : i - 10 + 'a');
    378 }
    379 ```
    380 
    381 When generating the code above, we pass the `hexDigit()` method as an argument to the `byteToHex()`
    382 method using `$N`:
    383 
    384 ```java
    385 MethodSpec hexDigit = MethodSpec.methodBuilder("hexDigit")
    386     .addParameter(int.class, "i")
    387     .returns(char.class)
    388     .addStatement("return (char) (i < 10 ? i + '0' : i - 10 + 'a')")
    389     .build();
    390 
    391 MethodSpec byteToHex = MethodSpec.methodBuilder("byteToHex")
    392     .addParameter(int.class, "b")
    393     .returns(String.class)
    394     .addStatement("char[] result = new char[2]")
    395     .addStatement("result[0] = $N((b >>> 4) & 0xf)", hexDigit)
    396     .addStatement("result[1] = $N(b & 0xf)", hexDigit)
    397     .addStatement("return new String(result)")
    398     .build();
    399 ```
    400 
    401 ### Code block format strings
    402 
    403 Code blocks may specify the values for their placeholders in a few ways. Only one style may be used
    404 for each operation on a code block.
    405 
    406 #### Relative Arguments
    407 
    408 Pass an argument value for each placeholder in the format string to `CodeBlock.add()`. In each
    409 example, we generate code to say "I ate 3 tacos"
    410 
    411 ```java
    412 CodeBlock.builder().add("I ate $L $L", 3, "tacos")
    413 ```
    414 
    415 #### Positional Arguments
    416 
    417 Place an integer index (1-based) before the placeholder in the format string to specify which
    418  argument to use.
    419 
    420 ```java
    421 CodeBlock.builder().add("I ate $2L $1L", "tacos", 3)
    422 ```
    423 
    424 #### Named Arguments
    425 
    426 Use the syntax `$argumentName:X` where `X` is the format character and call `CodeBlock.addNamed()`
    427 with a map containing all argument keys in the format string. Argument names use characters in
    428 `a-z`, `A-Z`, `0-9`, and `_`, and must start with a lowercase character.
    429 
    430 ```java
    431 Map<String, Object> map = new LinkedHashMap<>();
    432 map.put("food", "tacos");
    433 map.put("count", 3);
    434 CodeBlock.builder().addNamed("I ate $count:L $food:L", map)
    435 ```
    436 
    437 ### Methods
    438 
    439 All of the above methods have a code body. Use `Modifiers.ABSTRACT` to get a method without any
    440 body. This is only legal if the enclosing class is either abstract or an interface.
    441 
    442 ```java
    443 MethodSpec flux = MethodSpec.methodBuilder("flux")
    444     .addModifiers(Modifier.ABSTRACT, Modifier.PROTECTED)
    445     .build();
    446 
    447 TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
    448     .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
    449     .addMethod(flux)
    450     .build();
    451 ```
    452 
    453 Which generates this:
    454 
    455 ```java
    456 public abstract class HelloWorld {
    457   protected abstract void flux();
    458 }
    459 ```
    460 
    461 The other modifiers work where permitted. Note that when specifying modifiers, JavaPoet uses
    462 [`javax.lang.model.element.Modifier`][modifier], a class that is not available on Android. This
    463 limitation applies to code-generating-code only; the output code runs everywhere: JVMs, Android,
    464 and GWT.
    465 
    466 Methods also have parameters, exceptions, varargs, Javadoc, annotations, type variables, and a
    467 return type. All of these are configured with `MethodSpec.Builder`.
    468 
    469 ### Constructors
    470 
    471 `MethodSpec` is a slight misnomer; it can also be used for constructors:
    472 
    473 ```java
    474 MethodSpec flux = MethodSpec.constructorBuilder()
    475     .addModifiers(Modifier.PUBLIC)
    476     .addParameter(String.class, "greeting")
    477     .addStatement("this.$N = $N", "greeting", "greeting")
    478     .build();
    479 
    480 TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
    481     .addModifiers(Modifier.PUBLIC)
    482     .addField(String.class, "greeting", Modifier.PRIVATE, Modifier.FINAL)
    483     .addMethod(flux)
    484     .build();
    485 ```
    486 
    487 Which generates this:
    488 
    489 ```java
    490 public class HelloWorld {
    491   private final String greeting;
    492 
    493   public HelloWorld(String greeting) {
    494     this.greeting = greeting;
    495   }
    496 }
    497 ```
    498 
    499 For the most part, constructors work just like methods. When emitting code, JavaPoet will place
    500 constructors before methods in the output file.
    501 
    502 ### Parameters
    503 
    504 Declare parameters on methods and constructors with either `ParameterSpec.builder()` or
    505 `MethodSpec`'s convenient `addParameter()` API:
    506 
    507 ```java
    508 ParameterSpec android = ParameterSpec.builder(String.class, "android")
    509     .addModifiers(Modifier.FINAL)
    510     .build();
    511 
    512 MethodSpec welcomeOverlords = MethodSpec.methodBuilder("welcomeOverlords")
    513     .addParameter(android)
    514     .addParameter(String.class, "robot", Modifier.FINAL)
    515     .build();
    516 ```
    517 
    518 Though the code above to generate `android` and `robot` parameters is different, the output is the
    519 same:
    520 
    521 ```java
    522 void welcomeOverlords(final String android, final String robot) {
    523 }
    524 ```
    525 
    526 The extended `Builder` form is necessary when the parameter has annotations (such as `@Nullable`).
    527 
    528 ### Fields
    529 
    530 Like parameters, fields can be created either with builders or by using convenient helper methods:
    531 
    532 ```java
    533 FieldSpec android = FieldSpec.builder(String.class, "android")
    534     .addModifiers(Modifier.PRIVATE, Modifier.FINAL)
    535     .build();
    536 
    537 TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
    538     .addModifiers(Modifier.PUBLIC)
    539     .addField(android)
    540     .addField(String.class, "robot", Modifier.PRIVATE, Modifier.FINAL)
    541     .build();
    542 ```
    543 
    544 Which generates:
    545 
    546 ```java
    547 public class HelloWorld {
    548   private final String android;
    549 
    550   private final String robot;
    551 }
    552 ```
    553 
    554 The extended `Builder` form is necessary when a field has Javadoc, annotations, or a field
    555 initializer. Field initializers use the same [`String.format()`][formatter]-like syntax as the code
    556 blocks above:
    557 
    558 ```java
    559 FieldSpec android = FieldSpec.builder(String.class, "android")
    560     .addModifiers(Modifier.PRIVATE, Modifier.FINAL)
    561     .initializer("$S + $L", "Lollipop v.", 5.0d)
    562     .build();
    563 ```
    564 
    565 Which generates:
    566 
    567 ```java
    568 private final String android = "Lollipop v." + 5.0;
    569 ```
    570 
    571 ### Interfaces
    572 
    573 JavaPoet has no trouble with interfaces. Note that interface methods must always be `PUBLIC
    574 ABSTRACT` and interface fields must always be `PUBLIC STATIC FINAL`. These modifiers are necessary
    575 when defining the interface:
    576 
    577 ```java
    578 TypeSpec helloWorld = TypeSpec.interfaceBuilder("HelloWorld")
    579     .addModifiers(Modifier.PUBLIC)
    580     .addField(FieldSpec.builder(String.class, "ONLY_THING_THAT_IS_CONSTANT")
    581         .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
    582         .initializer("$S", "change")
    583         .build())
    584     .addMethod(MethodSpec.methodBuilder("beep")
    585         .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
    586         .build())
    587     .build();
    588 ```
    589 
    590 But these modifiers are omitted when the code is generated. These are the defaults so we don't need
    591 to include them for `javac`'s benefit!
    592 
    593 ```java
    594 public interface HelloWorld {
    595   String ONLY_THING_THAT_IS_CONSTANT = "change";
    596 
    597   void beep();
    598 }
    599 ```
    600 
    601 ### Enums
    602 
    603 Use `enumBuilder` to create the enum type, and `addEnumConstant()` for each value:
    604 
    605 ```java
    606 TypeSpec helloWorld = TypeSpec.enumBuilder("Roshambo")
    607     .addModifiers(Modifier.PUBLIC)
    608     .addEnumConstant("ROCK")
    609     .addEnumConstant("SCISSORS")
    610     .addEnumConstant("PAPER")
    611     .build();
    612 ```
    613 
    614 To generate this:
    615 
    616 ```java
    617 public enum Roshambo {
    618   ROCK,
    619 
    620   SCISSORS,
    621 
    622   PAPER
    623 }
    624 ```
    625 
    626 Fancy enums are supported, where the enum values override methods or call a superclass constructor.
    627 Here's a comprehensive example:
    628 
    629 ```java
    630 TypeSpec helloWorld = TypeSpec.enumBuilder("Roshambo")
    631     .addModifiers(Modifier.PUBLIC)
    632     .addEnumConstant("ROCK", TypeSpec.anonymousClassBuilder("$S", "fist")
    633         .addMethod(MethodSpec.methodBuilder("toString")
    634             .addAnnotation(Override.class)
    635             .addModifiers(Modifier.PUBLIC)
    636             .addStatement("return $S", "avalanche!")
    637             .returns(String.class)
    638             .build())
    639         .build())
    640     .addEnumConstant("SCISSORS", TypeSpec.anonymousClassBuilder("$S", "peace")
    641         .build())
    642     .addEnumConstant("PAPER", TypeSpec.anonymousClassBuilder("$S", "flat")
    643         .build())
    644     .addField(String.class, "handsign", Modifier.PRIVATE, Modifier.FINAL)
    645     .addMethod(MethodSpec.constructorBuilder()
    646         .addParameter(String.class, "handsign")
    647         .addStatement("this.$N = $N", "handsign", "handsign")
    648         .build())
    649     .build();
    650 ```
    651 
    652 Which generates this:
    653 
    654 ```java
    655 public enum Roshambo {
    656   ROCK("fist") {
    657     @Override
    658     public String toString() {
    659       return "avalanche!";
    660     }
    661   },
    662 
    663   SCISSORS("peace"),
    664 
    665   PAPER("flat");
    666 
    667   private final String handsign;
    668 
    669   Roshambo(String handsign) {
    670     this.handsign = handsign;
    671   }
    672 }
    673 ```
    674 
    675 ### Anonymous Inner Classes
    676 
    677 In the enum code, we used `Types.anonymousInnerClass()`. Anonymous inner classes can also be used in
    678 code blocks. They are values that can be referenced with `$L`:
    679 
    680 ```java
    681 TypeSpec comparator = TypeSpec.anonymousClassBuilder("")
    682     .addSuperinterface(ParameterizedTypeName.get(Comparator.class, String.class))
    683     .addMethod(MethodSpec.methodBuilder("compare")
    684         .addAnnotation(Override.class)
    685         .addModifiers(Modifier.PUBLIC)
    686         .addParameter(String.class, "a")
    687         .addParameter(String.class, "b")
    688         .returns(int.class)
    689         .addStatement("return $N.length() - $N.length()", "a", "b")
    690         .build())
    691     .build();
    692 
    693 TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
    694     .addMethod(MethodSpec.methodBuilder("sortByLength")
    695         .addParameter(ParameterizedTypeName.get(List.class, String.class), "strings")
    696         .addStatement("$T.sort($N, $L)", Collections.class, "strings", comparator)
    697         .build())
    698     .build();
    699 ```
    700 
    701 This generates a method that contains a class that contains a method:
    702 
    703 ```java
    704 void sortByLength(List<String> strings) {
    705   Collections.sort(strings, new Comparator<String>() {
    706     @Override
    707     public int compare(String a, String b) {
    708       return a.length() - b.length();
    709     }
    710   });
    711 }
    712 ```
    713 
    714 One particularly tricky part of defining anonymous inner classes is the arguments to the superclass
    715 constructor. In the above code we're passing the empty string for no arguments:
    716 `TypeSpec.anonymousClassBuilder("")`. To pass different parameters use JavaPoet's code block
    717 syntax with commas to separate arguments.
    718 
    719 
    720 ### Annotations
    721 
    722 Simple annotations are easy:
    723 
    724 ```java
    725 MethodSpec toString = MethodSpec.methodBuilder("toString")
    726     .addAnnotation(Override.class)
    727     .returns(String.class)
    728     .addModifiers(Modifier.PUBLIC)
    729     .addStatement("return $S", "Hoverboard")
    730     .build();
    731 ```
    732 
    733 Which generates this method with an `@Override` annotation:
    734 
    735 ```java
    736   @Override
    737   public String toString() {
    738     return "Hoverboard";
    739   }
    740 ```
    741 
    742 Use `AnnotationSpec.builder()` to set properties on annotations:
    743 
    744 ```java
    745 MethodSpec logRecord = MethodSpec.methodBuilder("recordEvent")
    746     .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
    747     .addAnnotation(AnnotationSpec.builder(Headers.class)
    748         .addMember("accept", "$S", "application/json; charset=utf-8")
    749         .addMember("userAgent", "$S", "Square Cash")
    750         .build())
    751     .addParameter(LogRecord.class, "logRecord")
    752     .returns(LogReceipt.class)
    753     .build();
    754 ```
    755 
    756 Which generates this annotation with `accept` and `userAgent` properties:
    757 
    758 ```java
    759 @Headers(
    760     accept = "application/json; charset=utf-8",
    761     userAgent = "Square Cash"
    762 )
    763 LogReceipt recordEvent(LogRecord logRecord);
    764 ```
    765 
    766 When you get fancy, annotation values can be annotations themselves. Use `$L` for embedded
    767 annotations:
    768 
    769 ```java
    770 MethodSpec logRecord = MethodSpec.methodBuilder("recordEvent")
    771     .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
    772     .addAnnotation(AnnotationSpec.builder(HeaderList.class)
    773         .addMember("value", "$L", AnnotationSpec.builder(Header.class)
    774             .addMember("name", "$S", "Accept")
    775             .addMember("value", "$S", "application/json; charset=utf-8")
    776             .build())
    777         .addMember("value", "$L", AnnotationSpec.builder(Header.class)
    778             .addMember("name", "$S", "User-Agent")
    779             .addMember("value", "$S", "Square Cash")
    780             .build())
    781         .build())
    782     .addParameter(LogRecord.class, "logRecord")
    783     .returns(LogReceipt.class)
    784     .build();
    785 ```
    786 
    787 Which generates this:
    788 
    789 ```java
    790 @HeaderList({
    791     @Header(name = "Accept", value = "application/json; charset=utf-8"),
    792     @Header(name = "User-Agent", value = "Square Cash")
    793 })
    794 LogReceipt recordEvent(LogRecord logRecord);
    795 ```
    796 
    797 Note that you can call `addMember()` multiple times with the same property name to populate a list
    798 of values for that property.
    799 
    800 ### Javadoc
    801 
    802 Fields, methods and types can be documented with Javadoc:
    803 
    804 ```java
    805 MethodSpec dismiss = MethodSpec.methodBuilder("dismiss")
    806     .addJavadoc("Hides {@code message} from the caller's history. Other\n"
    807         + "participants in the conversation will continue to see the\n"
    808         + "message in their own history unless they also delete it.\n")
    809     .addJavadoc("\n")
    810     .addJavadoc("<p>Use {@link #delete($T)} to delete the entire\n"
    811         + "conversation for all participants.\n", Conversation.class)
    812     .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
    813     .addParameter(Message.class, "message")
    814     .build();
    815 ```
    816 
    817 Which generates this:
    818 
    819 ```java
    820   /**
    821    * Hides {@code message} from the caller's history. Other
    822    * participants in the conversation will continue to see the
    823    * message in their own history unless they also delete it.
    824    *
    825    * <p>Use {@link #delete(Conversation)} to delete the entire
    826    * conversation for all participants.
    827    */
    828   void dismiss(Message message);
    829 ```
    830 
    831 Use `$T` when referencing types in Javadoc to get automatic imports.
    832 
    833 Download
    834 --------
    835 
    836 Download [the latest .jar][dl] or depend via Maven:
    837 ```xml
    838 <dependency>
    839   <groupId>com.squareup</groupId>
    840   <artifactId>javapoet</artifactId>
    841   <version>1.11.1</version>
    842 </dependency>
    843 ```
    844 or Gradle:
    845 ```groovy
    846 compile 'com.squareup:javapoet:1.11.1'
    847 ```
    848 
    849 Snapshots of the development version are available in [Sonatype's `snapshots` repository][snap].
    850 
    851 
    852 
    853 License
    854 -------
    855 
    856     Copyright 2015 Square, Inc.
    857 
    858     Licensed under the Apache License, Version 2.0 (the "License");
    859     you may not use this file except in compliance with the License.
    860     You may obtain a copy of the License at
    861 
    862        http://www.apache.org/licenses/LICENSE-2.0
    863 
    864     Unless required by applicable law or agreed to in writing, software
    865     distributed under the License is distributed on an "AS IS" BASIS,
    866     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    867     See the License for the specific language governing permissions and
    868     limitations under the License.
    869 
    870 
    871 
    872 JavaWriter
    873 ==========
    874 
    875 JavaPoet is the successor to [JavaWriter][javawriter]. New projects should prefer JavaPoet because
    876 it has a stronger code model: it understands types and can manage imports automatically. JavaPoet is
    877 also better suited to composition: rather than streaming the contents of a `.java` file
    878 top-to-bottom in a single pass, a file can be assembled as a tree of declarations.
    879 
    880 JavaWriter continues to be available in [GitHub][javawriter] and [Maven Central][javawriter_maven].
    881 
    882 
    883  [dl]: https://search.maven.org/remote_content?g=com.squareup&a=javapoet&v=LATEST
    884  [snap]: https://oss.sonatype.org/content/repositories/snapshots/com/squareup/javapoet/
    885  [javadoc]: https://square.github.io/javapoet/1.x/javapoet/
    886  [javawriter]: https://github.com/square/javapoet/tree/javawriter_2
    887  [javawriter_maven]: https://search.maven.org/#artifactdetails%7Ccom.squareup%7Cjavawriter%7C2.5.1%7Cjar
    888  [formatter]: https://developer.android.com/reference/java/util/Formatter.html
    889  [modifier]: https://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/Modifier.html
    890