• Home
Name Date Size #Lines LOC

..--

.buildscript/03-May-2024-3726

src/03-May-2024-12,1309,583

.gitignoreD03-May-2024150 2418

.travis.ymlD03-May-2024708 3123

Android.bpD03-May-20241.1 KiB3934

CHANGELOG.mdD03-May-202412.3 KiB340230

CONTRIBUTING.mdD03-May-2024722 1812

LICENSED03-May-202411.1 KiB203169

LICENSE.txtD03-May-202411.1 KiB203169

METADATAD03-May-2024368 2019

MODULE_LICENSE_APACHE2D03-May-20240

OWNERSD03-May-202462 43

README.mdD03-May-202427.4 KiB944740

checkstyle.xmlD03-May-20245.4 KiB14985

pom.xmlD03-May-20244.7 KiB160144

README.md

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