xref: /aosp_15_r20/external/auto/value/userguide/autobuilder.md (revision 1c2bbba85eccddce6de79cbbf1645fda32e723f0)
1*1c2bbba8SAndroid Build Coastguard Worker# AutoBuilder
2*1c2bbba8SAndroid Build Coastguard Worker
3*1c2bbba8SAndroid Build Coastguard Worker
4*1c2bbba8SAndroid Build Coastguard WorkerAutoBuilder makes it easy to create a generalized builder, with setter methods
5*1c2bbba8SAndroid Build Coastguard Workerthat accumulate values, and a build method that calls a constructor or static
6*1c2bbba8SAndroid Build Coastguard Workermethod with those values as parameters. Callers don't need to know the order of
7*1c2bbba8SAndroid Build Coastguard Workerthose parameters. Parameters can also have default values. There can be
8*1c2bbba8SAndroid Build Coastguard Workervalidation before the constructor or method call.
9*1c2bbba8SAndroid Build Coastguard Worker
10*1c2bbba8SAndroid Build Coastguard WorkerIf you are familiar with [AutoValue builders](builders.md) then AutoBuilder
11*1c2bbba8SAndroid Build Coastguard Workershould also be familiar. Where an `@AutoValue.Builder` has setter methods
12*1c2bbba8SAndroid Build Coastguard Workercorresponding to the getter methods in the `@AutoValue` class, an `@AutoBuilder`
13*1c2bbba8SAndroid Build Coastguard Workerhas setter methods corresponding to the parameters of a constructor or static
14*1c2bbba8SAndroid Build Coastguard Workermethod. Apart from that, the two are very similar.
15*1c2bbba8SAndroid Build Coastguard Worker
16*1c2bbba8SAndroid Build Coastguard Worker## Example: calling a constructor
17*1c2bbba8SAndroid Build Coastguard Worker
18*1c2bbba8SAndroid Build Coastguard WorkerHere is a simple example:
19*1c2bbba8SAndroid Build Coastguard Worker
20*1c2bbba8SAndroid Build Coastguard Worker```java
21*1c2bbba8SAndroid Build Coastguard Worker@AutoBuilder(ofClass = Person.class)
22*1c2bbba8SAndroid Build Coastguard Workerabstract class PersonBuilder {
23*1c2bbba8SAndroid Build Coastguard Worker  static PersonBuilder personBuilder() {
24*1c2bbba8SAndroid Build Coastguard Worker    return new AutoBuilder_PersonBuilder();
25*1c2bbba8SAndroid Build Coastguard Worker  }
26*1c2bbba8SAndroid Build Coastguard Worker
27*1c2bbba8SAndroid Build Coastguard Worker  abstract PersonBuilder setName(String name);
28*1c2bbba8SAndroid Build Coastguard Worker  abstract PersonBuilder setId(int id);
29*1c2bbba8SAndroid Build Coastguard Worker  abstract Person build();
30*1c2bbba8SAndroid Build Coastguard Worker}
31*1c2bbba8SAndroid Build Coastguard Worker```
32*1c2bbba8SAndroid Build Coastguard Worker
33*1c2bbba8SAndroid Build Coastguard WorkerIt might be used like this:
34*1c2bbba8SAndroid Build Coastguard Worker
35*1c2bbba8SAndroid Build Coastguard Worker```java
36*1c2bbba8SAndroid Build Coastguard WorkerPerson p = PersonBuilder.personBuilder().setName("Priz").setId(6).build();
37*1c2bbba8SAndroid Build Coastguard Worker```
38*1c2bbba8SAndroid Build Coastguard Worker
39*1c2bbba8SAndroid Build Coastguard WorkerThat would have the same effect as this:
40*1c2bbba8SAndroid Build Coastguard Worker
41*1c2bbba8SAndroid Build Coastguard Worker```java
42*1c2bbba8SAndroid Build Coastguard WorkerPerson p = new Person("Priz", 6);
43*1c2bbba8SAndroid Build Coastguard Worker```
44*1c2bbba8SAndroid Build Coastguard Worker
45*1c2bbba8SAndroid Build Coastguard WorkerBut it doesn't require you to know what order the constructor parameters are in.
46*1c2bbba8SAndroid Build Coastguard Worker
47*1c2bbba8SAndroid Build Coastguard WorkerHere, `setName` and `setId` are _setter methods_. Calling
48*1c2bbba8SAndroid Build Coastguard Worker`builder.setName("Priz")` records the value `"Priz"` for the parameter `name`,
49*1c2bbba8SAndroid Build Coastguard Workerand likewise with `setId`.
50*1c2bbba8SAndroid Build Coastguard Worker
51*1c2bbba8SAndroid Build Coastguard WorkerThere is also a `build()` method. Calling that method invokes the `Person`
52*1c2bbba8SAndroid Build Coastguard Workerconstructor with the parameters that were previously set.
53*1c2bbba8SAndroid Build Coastguard Worker
54*1c2bbba8SAndroid Build Coastguard Worker## <a name="kotlin"></a> Example: calling a Kotlin constructor
55*1c2bbba8SAndroid Build Coastguard Worker
56*1c2bbba8SAndroid Build Coastguard WorkerKotlin has named arguments and default arguments for constructors and functions,
57*1c2bbba8SAndroid Build Coastguard Workerwhich means there is not much need for anything like AutoBuilder there. But if
58*1c2bbba8SAndroid Build Coastguard Workeryou are constructing an instance of a Kotlin data class from Java code,
59*1c2bbba8SAndroid Build Coastguard WorkerAutoBuilder can help.
60*1c2bbba8SAndroid Build Coastguard Worker
61*1c2bbba8SAndroid Build Coastguard WorkerGiven this trivial Kotlin data class:
62*1c2bbba8SAndroid Build Coastguard Worker
63*1c2bbba8SAndroid Build Coastguard Worker```kotlin
64*1c2bbba8SAndroid Build Coastguard Workerclass KotlinData(val level: Int, val name: String?, val id: Long = -1L)
65*1c2bbba8SAndroid Build Coastguard Worker```
66*1c2bbba8SAndroid Build Coastguard Worker
67*1c2bbba8SAndroid Build Coastguard WorkerYou might make a builder for it like this:
68*1c2bbba8SAndroid Build Coastguard Worker
69*1c2bbba8SAndroid Build Coastguard Worker```java
70*1c2bbba8SAndroid Build Coastguard Worker@AutoBuilder(ofClass = KotlinData.class)
71*1c2bbba8SAndroid Build Coastguard Workerpublic abstract class KotlinDataBuilder {
72*1c2bbba8SAndroid Build Coastguard Worker  public static KotlinDataBuilder kotlinDataBuilder() {
73*1c2bbba8SAndroid Build Coastguard Worker    return new AutoBuilder_KotlinDataBuilder();
74*1c2bbba8SAndroid Build Coastguard Worker  }
75*1c2bbba8SAndroid Build Coastguard Worker
76*1c2bbba8SAndroid Build Coastguard Worker  public abstract KotlinDataBuilder setLevel(int x);
77*1c2bbba8SAndroid Build Coastguard Worker  public abstract KotlinDataBuilder setName(@Nullable String x);
78*1c2bbba8SAndroid Build Coastguard Worker  public abstract KotlinDataBuilder setId(long x);
79*1c2bbba8SAndroid Build Coastguard Worker  public abstract KotlinData build();
80*1c2bbba8SAndroid Build Coastguard Worker}
81*1c2bbba8SAndroid Build Coastguard Worker```
82*1c2bbba8SAndroid Build Coastguard Worker
83*1c2bbba8SAndroid Build Coastguard WorkerThe Kotlin type `String?` corresponds to `@Nullable String` in the AutoBuilder
84*1c2bbba8SAndroid Build Coastguard Workerclass, where `@Nullable` is any annotation with that name, such as
85*1c2bbba8SAndroid Build Coastguard Worker`org.jetbrains.annotations.Nullable`.
86*1c2bbba8SAndroid Build Coastguard Worker
87*1c2bbba8SAndroid Build Coastguard WorkerThe `id` parameter has a default value of `-1L`, which means that if `setId` is
88*1c2bbba8SAndroid Build Coastguard Workernot called then the `id` field of the built `KotlinData` will be `-1L`.
89*1c2bbba8SAndroid Build Coastguard Worker
90*1c2bbba8SAndroid Build Coastguard WorkerIf you are using [kapt](https://kotlinlang.org/docs/kapt.html) then you can also
91*1c2bbba8SAndroid Build Coastguard Workerdefine the builder in the data class itself:
92*1c2bbba8SAndroid Build Coastguard Worker
93*1c2bbba8SAndroid Build Coastguard Worker```kotlin
94*1c2bbba8SAndroid Build Coastguard Workerclass KotlinData(val level: Int, val name: String?, val id: Long = -1L) {
95*1c2bbba8SAndroid Build Coastguard Worker  @AutoBuilder // we don't need ofClass: by default it is the containing class
96*1c2bbba8SAndroid Build Coastguard Worker  interface Builder {
97*1c2bbba8SAndroid Build Coastguard Worker    fun setLevel(x: Int): Builder
98*1c2bbba8SAndroid Build Coastguard Worker    fun setName(x: String?): Builder
99*1c2bbba8SAndroid Build Coastguard Worker    fun setId(x: Long): Builder
100*1c2bbba8SAndroid Build Coastguard Worker    fun build(): KotlinData
101*1c2bbba8SAndroid Build Coastguard Worker  }
102*1c2bbba8SAndroid Build Coastguard Worker
103*1c2bbba8SAndroid Build Coastguard Worker  fun toBuilder(): Builder = AutoBuilder_KotlinData_Builder(this)
104*1c2bbba8SAndroid Build Coastguard Worker
105*1c2bbba8SAndroid Build Coastguard Worker  companion object {
106*1c2bbba8SAndroid Build Coastguard Worker    @JvmStatic fun builder(): Builder = AutoBuilder_KotlinData_Builder()
107*1c2bbba8SAndroid Build Coastguard Worker  }
108*1c2bbba8SAndroid Build Coastguard Worker}
109*1c2bbba8SAndroid Build Coastguard Worker```
110*1c2bbba8SAndroid Build Coastguard Worker
111*1c2bbba8SAndroid Build Coastguard WorkerThis example uses an interface rather than an abstract class for the builder,
112*1c2bbba8SAndroid Build Coastguard Workerbut both are possible. Java code would then construct instances like this:
113*1c2bbba8SAndroid Build Coastguard Worker
114*1c2bbba8SAndroid Build Coastguard Worker```java
115*1c2bbba8SAndroid Build Coastguard WorkerKotlinData k = KotlinData.builder().setLevel(23).build();
116*1c2bbba8SAndroid Build Coastguard Worker```
117*1c2bbba8SAndroid Build Coastguard Worker
118*1c2bbba8SAndroid Build Coastguard WorkerThe example also implements a `toBuilder()` method to get a builder that starts
119*1c2bbba8SAndroid Build Coastguard Workerout with values from the given instance. See [below](#to_builder) for more
120*1c2bbba8SAndroid Build Coastguard Workerdetails on that.
121*1c2bbba8SAndroid Build Coastguard Worker
122*1c2bbba8SAndroid Build Coastguard Worker## The generated subclass
123*1c2bbba8SAndroid Build Coastguard Worker
124*1c2bbba8SAndroid Build Coastguard WorkerLike `@AutoValue.Builder`, compiling an `@AutoBuilder` class will generate a
125*1c2bbba8SAndroid Build Coastguard Workerconcrete subclass. In the example above, this will be `class
126*1c2bbba8SAndroid Build Coastguard WorkerAutoBuilder_PersonBuilder extends PersonBuilder`. It is common to have a static
127*1c2bbba8SAndroid Build Coastguard Worker`builder()` method, as in the example, which calls `new AutoBuilder_...()`. That
128*1c2bbba8SAndroid Build Coastguard Workerwill typically be the only reference to the generated class.
129*1c2bbba8SAndroid Build Coastguard Worker
130*1c2bbba8SAndroid Build Coastguard WorkerIf the `@AutoBuilder` type is nested then the name of the generated class
131*1c2bbba8SAndroid Build Coastguard Workerreflects that nesting. For example:
132*1c2bbba8SAndroid Build Coastguard Worker
133*1c2bbba8SAndroid Build Coastguard Worker```java
134*1c2bbba8SAndroid Build Coastguard Workerclass Outer {
135*1c2bbba8SAndroid Build Coastguard Worker  static class Inner {
136*1c2bbba8SAndroid Build Coastguard Worker    @AutoBuilder
137*1c2bbba8SAndroid Build Coastguard Worker    abstract static class Builder {...}
138*1c2bbba8SAndroid Build Coastguard Worker  }
139*1c2bbba8SAndroid Build Coastguard Worker  static Inner.Builder builder() {
140*1c2bbba8SAndroid Build Coastguard Worker    return new AutoBuilder_Outer_Inner_Builder();
141*1c2bbba8SAndroid Build Coastguard Worker  }
142*1c2bbba8SAndroid Build Coastguard Worker}
143*1c2bbba8SAndroid Build Coastguard Worker```
144*1c2bbba8SAndroid Build Coastguard Worker
145*1c2bbba8SAndroid Build Coastguard Worker## `@AutoBuilder` annotation parameters
146*1c2bbba8SAndroid Build Coastguard Worker
147*1c2bbba8SAndroid Build Coastguard Worker`@AutoBuilder` has two annotation parameters, `ofClass` and `callMethod`.
148*1c2bbba8SAndroid Build Coastguard Worker
149*1c2bbba8SAndroid Build Coastguard WorkerIf `ofClass` is specified, then `build()` will call a constructor or static
150*1c2bbba8SAndroid Build Coastguard Workermethod of that class. Otherwise it will call a constructor or static method of
151*1c2bbba8SAndroid Build Coastguard Workerthe class _containing_ the `@AutoBuilder` class.
152*1c2bbba8SAndroid Build Coastguard Worker
153*1c2bbba8SAndroid Build Coastguard WorkerIf `callMethod` is specified, then `build()` will call a static method with that
154*1c2bbba8SAndroid Build Coastguard Workername. Otherwise `build()` will call a constructor.
155*1c2bbba8SAndroid Build Coastguard Worker
156*1c2bbba8SAndroid Build Coastguard WorkerThe following examples illustrate the various possibilities. These examples use
157*1c2bbba8SAndroid Build Coastguard Workeran interface for the `@AutoBuilder` type. You can also use an abstract class; if
158*1c2bbba8SAndroid Build Coastguard Workerit is nested then it must be static.
159*1c2bbba8SAndroid Build Coastguard Worker
160*1c2bbba8SAndroid Build Coastguard Worker### Both `callMethod` and `ofClass`
161*1c2bbba8SAndroid Build Coastguard Worker
162*1c2bbba8SAndroid Build Coastguard Worker```java
163*1c2bbba8SAndroid Build Coastguard Worker@AutoBuilder(callMethod = "of", ofClass = LocalTime.class)
164*1c2bbba8SAndroid Build Coastguard Workerinterface LocalTimeBuilder {
165*1c2bbba8SAndroid Build Coastguard Worker  ...
166*1c2bbba8SAndroid Build Coastguard Worker  LocalTime build(); // calls: LocalTime.of(...)
167*1c2bbba8SAndroid Build Coastguard Worker}
168*1c2bbba8SAndroid Build Coastguard Worker```
169*1c2bbba8SAndroid Build Coastguard Worker
170*1c2bbba8SAndroid Build Coastguard Worker### Only `ofClass`
171*1c2bbba8SAndroid Build Coastguard Worker
172*1c2bbba8SAndroid Build Coastguard Worker```java
173*1c2bbba8SAndroid Build Coastguard Worker@AutoBuilder(ofClass = Thread.class)
174*1c2bbba8SAndroid Build Coastguard Workerinterface ThreadBuilder {
175*1c2bbba8SAndroid Build Coastguard Worker  ...
176*1c2bbba8SAndroid Build Coastguard Worker  Thread build(); // calls: new Thread(...)
177*1c2bbba8SAndroid Build Coastguard Worker}
178*1c2bbba8SAndroid Build Coastguard Worker```
179*1c2bbba8SAndroid Build Coastguard Worker
180*1c2bbba8SAndroid Build Coastguard Worker### Only `callMethod`
181*1c2bbba8SAndroid Build Coastguard Worker
182*1c2bbba8SAndroid Build Coastguard Worker```java
183*1c2bbba8SAndroid Build Coastguard Workerclass Foo {
184*1c2bbba8SAndroid Build Coastguard Worker  static String concat(String first, String middle, String last) {...}
185*1c2bbba8SAndroid Build Coastguard Worker
186*1c2bbba8SAndroid Build Coastguard Worker  @AutoBuilder(callMethod = "concat")
187*1c2bbba8SAndroid Build Coastguard Worker  interface ConcatBuilder {
188*1c2bbba8SAndroid Build Coastguard Worker    ...
189*1c2bbba8SAndroid Build Coastguard Worker    String build(); // calls: Foo.concat(first, middle, last)
190*1c2bbba8SAndroid Build Coastguard Worker  }
191*1c2bbba8SAndroid Build Coastguard Worker}
192*1c2bbba8SAndroid Build Coastguard Worker```
193*1c2bbba8SAndroid Build Coastguard Worker
194*1c2bbba8SAndroid Build Coastguard WorkerNotice in this example that the static method returns `String`. The implicit
195*1c2bbba8SAndroid Build Coastguard Worker`ofClass` is `Foo`, but the static method can return any type.
196*1c2bbba8SAndroid Build Coastguard Worker
197*1c2bbba8SAndroid Build Coastguard Worker### Neither `callMethod` nor `ofClass`
198*1c2bbba8SAndroid Build Coastguard Worker
199*1c2bbba8SAndroid Build Coastguard Worker```java
200*1c2bbba8SAndroid Build Coastguard Workerclass Person {
201*1c2bbba8SAndroid Build Coastguard Worker  Person(String name, int id) {...}
202*1c2bbba8SAndroid Build Coastguard Worker
203*1c2bbba8SAndroid Build Coastguard Worker  @AutoBuilder
204*1c2bbba8SAndroid Build Coastguard Worker  interface Builder {
205*1c2bbba8SAndroid Build Coastguard Worker    ...
206*1c2bbba8SAndroid Build Coastguard Worker    Person build(); // calls: new Person(name, id)
207*1c2bbba8SAndroid Build Coastguard Worker  }
208*1c2bbba8SAndroid Build Coastguard Worker}
209*1c2bbba8SAndroid Build Coastguard Worker```
210*1c2bbba8SAndroid Build Coastguard Worker
211*1c2bbba8SAndroid Build Coastguard Worker## The build method
212*1c2bbba8SAndroid Build Coastguard Worker
213*1c2bbba8SAndroid Build Coastguard WorkerThe build method must have a certain return type. If it calls a constructor then
214*1c2bbba8SAndroid Build Coastguard Workerits return type must be the type of the constructed class. If it calls a static
215*1c2bbba8SAndroid Build Coastguard Workermethod then its return type must be the return type of the static method.
216*1c2bbba8SAndroid Build Coastguard Worker
217*1c2bbba8SAndroid Build Coastguard WorkerThe build method is often called `build()` but it does not have to be. The only
218*1c2bbba8SAndroid Build Coastguard Workerrequirement is that there must be exactly one no-arg abstract method that has
219*1c2bbba8SAndroid Build Coastguard Workerthe return type just described and that does not correspond to a parameter name.
220*1c2bbba8SAndroid Build Coastguard Worker
221*1c2bbba8SAndroid Build Coastguard WorkerThe following example uses the name `call()` since that more accurately reflects
222*1c2bbba8SAndroid Build Coastguard Workerwhat it does:
223*1c2bbba8SAndroid Build Coastguard Worker
224*1c2bbba8SAndroid Build Coastguard Worker```java
225*1c2bbba8SAndroid Build Coastguard Workerpublic class LogUtil {
226*1c2bbba8SAndroid Build Coastguard Worker  public static void log(Level severity, String message, Object... params) {...}
227*1c2bbba8SAndroid Build Coastguard Worker
228*1c2bbba8SAndroid Build Coastguard Worker  @AutoBuilder(callMethod = "log")
229*1c2bbba8SAndroid Build Coastguard Worker  public interface Caller {
230*1c2bbba8SAndroid Build Coastguard Worker    Caller setSeverity(Level level);
231*1c2bbba8SAndroid Build Coastguard Worker    Caller setMessage(String message);
232*1c2bbba8SAndroid Build Coastguard Worker    Caller setParams(Object... params);
233*1c2bbba8SAndroid Build Coastguard Worker    void call(); // calls: LogUtil.log(severity, message, params)
234*1c2bbba8SAndroid Build Coastguard Worker  }
235*1c2bbba8SAndroid Build Coastguard Worker```
236*1c2bbba8SAndroid Build Coastguard Worker
237*1c2bbba8SAndroid Build Coastguard Worker## <a name="to_builder"></a> Making a builder from a built instance
238*1c2bbba8SAndroid Build Coastguard Worker
239*1c2bbba8SAndroid Build Coastguard WorkerIt is not always possible to map back from the result of a constructor or method
240*1c2bbba8SAndroid Build Coastguard Workercall to a builder that might have produced it. But in one important case, it
241*1c2bbba8SAndroid Build Coastguard Worker*is* possible. That's when every parameter in the constructor or method
242*1c2bbba8SAndroid Build Coastguard Workercorresponds to a "getter method" in the built type. This will always be true
243*1c2bbba8SAndroid Build Coastguard Workerwhen building a Java record or a Kotlin data class (provided its getters are
244*1c2bbba8SAndroid Build Coastguard Workervisible to the builder). In this case, the generated builder class will have a
245*1c2bbba8SAndroid Build Coastguard Workersecond constructor that takes an object of the built type as a parameter and
246*1c2bbba8SAndroid Build Coastguard Workerproduces a builder that starts out with values from that object. That can then
247*1c2bbba8SAndroid Build Coastguard Workerbe used to produce a new object that may differ from the first one in just one
248*1c2bbba8SAndroid Build Coastguard Workeror two properties. (This is very similar to AutoValue's
249*1c2bbba8SAndroid Build Coastguard Worker[`toBuilder()`](builders-howto.md#to_builder) feature.)
250*1c2bbba8SAndroid Build Coastguard Worker
251*1c2bbba8SAndroid Build Coastguard WorkerIf the constructor or method has a parameter `String bar` then the built type
252*1c2bbba8SAndroid Build Coastguard Workermust have a visible method `String bar()` or `String getBar()`. (Java records
253*1c2bbba8SAndroid Build Coastguard Workerhave the first and Kotlin data classes have the second.) If there is a
254*1c2bbba8SAndroid Build Coastguard Workersimilar corresponding method for every parameter then the second constructor is
255*1c2bbba8SAndroid Build Coastguard Workergenerated.
256*1c2bbba8SAndroid Build Coastguard Worker
257*1c2bbba8SAndroid Build Coastguard WorkerIf you are able to change the built type, the most convenient way to use this is
258*1c2bbba8SAndroid Build Coastguard Workerto add a `toBuilder()` instance method that calls `new AutoBuilder_Foo(this)`.
259*1c2bbba8SAndroid Build Coastguard WorkerWe saw this in the [Kotlin example](#kotlin) earlier. Otherwise, you can have
260*1c2bbba8SAndroid Build Coastguard Workera second static `builder` method, like this:
261*1c2bbba8SAndroid Build Coastguard Worker
262*1c2bbba8SAndroid Build Coastguard Worker```java
263*1c2bbba8SAndroid Build Coastguard Worker@AutoBuilder(ofClass = Person.class)
264*1c2bbba8SAndroid Build Coastguard Workerabstract class PersonBuilder {
265*1c2bbba8SAndroid Build Coastguard Worker  static PersonBuilder personBuilder() {
266*1c2bbba8SAndroid Build Coastguard Worker    return new AutoBuilder_PersonBuilder();
267*1c2bbba8SAndroid Build Coastguard Worker  }
268*1c2bbba8SAndroid Build Coastguard Worker  static PersonBuilder personBuilder(Person person) {
269*1c2bbba8SAndroid Build Coastguard Worker    return new AutoBuilder_PersonBuilder(person);
270*1c2bbba8SAndroid Build Coastguard Worker  }
271*1c2bbba8SAndroid Build Coastguard Worker  ...
272*1c2bbba8SAndroid Build Coastguard Worker}
273*1c2bbba8SAndroid Build Coastguard Worker```
274*1c2bbba8SAndroid Build Coastguard Worker
275*1c2bbba8SAndroid Build Coastguard Worker## Overloaded constructors or methods
276*1c2bbba8SAndroid Build Coastguard Worker
277*1c2bbba8SAndroid Build Coastguard WorkerThere might be more than one constructor or static method that matches the
278*1c2bbba8SAndroid Build Coastguard Worker`callMethod` and `ofClass`. AutoBuilder will ignore any that are not visible to
279*1c2bbba8SAndroid Build Coastguard Workerthe generated class, meaning private, or package-private and in a different
280*1c2bbba8SAndroid Build Coastguard Workerpackage. Of the others, it will pick the one whose parameter names match the
281*1c2bbba8SAndroid Build Coastguard Worker`@AutoBuilder` setter methods. It is a compilation error if there is not exactly
282*1c2bbba8SAndroid Build Coastguard Workerone such method or constructor.
283*1c2bbba8SAndroid Build Coastguard Worker
284*1c2bbba8SAndroid Build Coastguard Worker## Generics
285*1c2bbba8SAndroid Build Coastguard Worker
286*1c2bbba8SAndroid Build Coastguard WorkerIf the builder calls the constructor of a generic type, then it must have the
287*1c2bbba8SAndroid Build Coastguard Workersame type parameters as that type, as in this example:
288*1c2bbba8SAndroid Build Coastguard Worker
289*1c2bbba8SAndroid Build Coastguard Worker```java
290*1c2bbba8SAndroid Build Coastguard Workerclass NumberPair<T extends Number> {
291*1c2bbba8SAndroid Build Coastguard Worker  NumberPair(T first, T second) {...}
292*1c2bbba8SAndroid Build Coastguard Worker
293*1c2bbba8SAndroid Build Coastguard Worker  @AutoBuilder
294*1c2bbba8SAndroid Build Coastguard Worker  interface Builder<T extends Number> {
295*1c2bbba8SAndroid Build Coastguard Worker    Builder<T> setFirst(T x);
296*1c2bbba8SAndroid Build Coastguard Worker    Builder<T> setSecond(T x);
297*1c2bbba8SAndroid Build Coastguard Worker    NumberPair<T> build();
298*1c2bbba8SAndroid Build Coastguard Worker  }
299*1c2bbba8SAndroid Build Coastguard Worker}
300*1c2bbba8SAndroid Build Coastguard Worker```
301*1c2bbba8SAndroid Build Coastguard Worker
302*1c2bbba8SAndroid Build Coastguard WorkerIf the builder calls a static method with type parameters, then it must have the
303*1c2bbba8SAndroid Build Coastguard Workersame type parameters, as in this example:
304*1c2bbba8SAndroid Build Coastguard Worker
305*1c2bbba8SAndroid Build Coastguard Worker```java
306*1c2bbba8SAndroid Build Coastguard Workerclass Utils {
307*1c2bbba8SAndroid Build Coastguard Worker  static <K extends Number, V> Map<K, V> singletonNumberMap(K key, V value) {...}
308*1c2bbba8SAndroid Build Coastguard Worker
309*1c2bbba8SAndroid Build Coastguard Worker  @AutoBuilder(callMethod = "singletonNumberMap")
310*1c2bbba8SAndroid Build Coastguard Worker  interface Builder<K extends Number, V> {
311*1c2bbba8SAndroid Build Coastguard Worker    Builder<K, V> setKey(K x);
312*1c2bbba8SAndroid Build Coastguard Worker    Builder<K, V> setValue(V x);
313*1c2bbba8SAndroid Build Coastguard Worker    Map<K, V> build();
314*1c2bbba8SAndroid Build Coastguard Worker  }
315*1c2bbba8SAndroid Build Coastguard Worker}
316*1c2bbba8SAndroid Build Coastguard Worker```
317*1c2bbba8SAndroid Build Coastguard Worker
318*1c2bbba8SAndroid Build Coastguard WorkerAlthough it's unusual, a Java constructor can have its own type parameters,
319*1c2bbba8SAndroid Build Coastguard Workerseparately from any that its containing class might have. A builder that calls a
320*1c2bbba8SAndroid Build Coastguard Workerconstructor like that must have the type parameters of the class followed by the
321*1c2bbba8SAndroid Build Coastguard Workertype parameters of the constructor:
322*1c2bbba8SAndroid Build Coastguard Worker
323*1c2bbba8SAndroid Build Coastguard Worker```java
324*1c2bbba8SAndroid Build Coastguard Workerclass CheckedSet<E> implements Set<E> {
325*1c2bbba8SAndroid Build Coastguard Worker  <T extends E> CheckedSet(Class<T> type) {...}
326*1c2bbba8SAndroid Build Coastguard Worker
327*1c2bbba8SAndroid Build Coastguard Worker  @AutoBuilder
328*1c2bbba8SAndroid Build Coastguard Worker  interface Builder<E, T extends E> {
329*1c2bbba8SAndroid Build Coastguard Worker    Builder<E, T> setType(Class<T> type);
330*1c2bbba8SAndroid Build Coastguard Worker    CheckedSet<E> build();
331*1c2bbba8SAndroid Build Coastguard Worker  }
332*1c2bbba8SAndroid Build Coastguard Worker}
333*1c2bbba8SAndroid Build Coastguard Worker```
334*1c2bbba8SAndroid Build Coastguard Worker
335*1c2bbba8SAndroid Build Coastguard Worker## Required, optional, and nullable parameters
336*1c2bbba8SAndroid Build Coastguard Worker
337*1c2bbba8SAndroid Build Coastguard WorkerParameters that are annotated `@Nullable` are null by default. Parameters of
338*1c2bbba8SAndroid Build Coastguard Workertype `Optional`, `OptionalInt`, `OptionalLong`, and `OptionalDouble` are empty
339*1c2bbba8SAndroid Build Coastguard Workerby default. Kotlin constructor parameters with default values get those values
340*1c2bbba8SAndroid Build Coastguard Workerby default. Every other parameter is _required_, meaning that the build method
341*1c2bbba8SAndroid Build Coastguard Workerwill throw `IllegalStateException` if any are omitted.
342*1c2bbba8SAndroid Build Coastguard Worker
343*1c2bbba8SAndroid Build Coastguard WorkerTo establish default values for parameters, set them in the `builder()` method
344*1c2bbba8SAndroid Build Coastguard Workerbefore returning the builder.
345*1c2bbba8SAndroid Build Coastguard Worker
346*1c2bbba8SAndroid Build Coastguard Worker```java
347*1c2bbba8SAndroid Build Coastguard Workerclass Foo {
348*1c2bbba8SAndroid Build Coastguard Worker  Foo(String bar, @Nullable String baz, String buh) {...}
349*1c2bbba8SAndroid Build Coastguard Worker
350*1c2bbba8SAndroid Build Coastguard Worker  static Builder builder() {
351*1c2bbba8SAndroid Build Coastguard Worker    return new AutoBuilder_Foo_Builder()
352*1c2bbba8SAndroid Build Coastguard Worker        .setBar(DEFAULT_BAR);
353*1c2bbba8SAndroid Build Coastguard Worker  }
354*1c2bbba8SAndroid Build Coastguard Worker
355*1c2bbba8SAndroid Build Coastguard Worker  @AutoBuilder
356*1c2bbba8SAndroid Build Coastguard Worker  interface Builder {
357*1c2bbba8SAndroid Build Coastguard Worker    Builder setBar(String x);
358*1c2bbba8SAndroid Build Coastguard Worker    Builder setBaz(String x);
359*1c2bbba8SAndroid Build Coastguard Worker    Builder setBuh(String x);
360*1c2bbba8SAndroid Build Coastguard Worker    Foo build();
361*1c2bbba8SAndroid Build Coastguard Worker  }
362*1c2bbba8SAndroid Build Coastguard Worker
363*1c2bbba8SAndroid Build Coastguard Worker  {
364*1c2bbba8SAndroid Build Coastguard Worker     builder().build(); // IllegalStateException, buh is not set
365*1c2bbba8SAndroid Build Coastguard Worker     builder().setBuh("buh").build(); // OK, bar=DEFAULT_BAR and baz=null
366*1c2bbba8SAndroid Build Coastguard Worker     builder().setBaz(null).setBuh("buh").build(); // OK
367*1c2bbba8SAndroid Build Coastguard Worker     builder().setBar(null); // NullPointerException, bar is not @Nullable
368*1c2bbba8SAndroid Build Coastguard Worker  }
369*1c2bbba8SAndroid Build Coastguard Worker}
370*1c2bbba8SAndroid Build Coastguard Worker```
371*1c2bbba8SAndroid Build Coastguard Worker
372*1c2bbba8SAndroid Build Coastguard WorkerTrying to set a parameter that is _not_ annotated `@Nullable` to `null` will
373*1c2bbba8SAndroid Build Coastguard Workerproduce a `NullPointerException`.
374*1c2bbba8SAndroid Build Coastguard Worker
375*1c2bbba8SAndroid Build Coastguard Worker`@Nullable` here is any annotation with that name, such as
376*1c2bbba8SAndroid Build Coastguard Worker`javax.annotation.Nullable` or
377*1c2bbba8SAndroid Build Coastguard Worker`org.checkerframework.checker.nullness.qual.Nullable`.
378*1c2bbba8SAndroid Build Coastguard Worker
379*1c2bbba8SAndroid Build Coastguard Worker## Getters
380*1c2bbba8SAndroid Build Coastguard Worker
381*1c2bbba8SAndroid Build Coastguard WorkerThe `@AutoBuilder` class or interface can also have _getter_ methods. A getter
382*1c2bbba8SAndroid Build Coastguard Workermethod returns the value that has been set for a certain parameter. Its return
383*1c2bbba8SAndroid Build Coastguard Workertype can be either the same as the parameter type, or an `Optional` wrapping
384*1c2bbba8SAndroid Build Coastguard Workerthat type. Calling the getter before any value has been set will throw an
385*1c2bbba8SAndroid Build Coastguard Workerexception in the first case or return an empty `Optional` in the second.
386*1c2bbba8SAndroid Build Coastguard Worker
387*1c2bbba8SAndroid Build Coastguard WorkerIn this example, the `nickname` parameter defaults to the same value as the
388*1c2bbba8SAndroid Build Coastguard Worker`name` parameter but can also be set to a different value:
389*1c2bbba8SAndroid Build Coastguard Worker
390*1c2bbba8SAndroid Build Coastguard Worker```java
391*1c2bbba8SAndroid Build Coastguard Workerpublic class Named {
392*1c2bbba8SAndroid Build Coastguard Worker  Named(String name, String nickname) {...}
393*1c2bbba8SAndroid Build Coastguard Worker
394*1c2bbba8SAndroid Build Coastguard Worker  @AutoBuilder
395*1c2bbba8SAndroid Build Coastguard Worker  public abstract static class Builder {
396*1c2bbba8SAndroid Build Coastguard Worker    public abstract Builder setName(String x);
397*1c2bbba8SAndroid Build Coastguard Worker    public abstract Builder setNickname(String x);
398*1c2bbba8SAndroid Build Coastguard Worker    abstract String getName();
399*1c2bbba8SAndroid Build Coastguard Worker    abstract Optional<String> getNickname();
400*1c2bbba8SAndroid Build Coastguard Worker    abstract Named autoBuild();
401*1c2bbba8SAndroid Build Coastguard Worker
402*1c2bbba8SAndroid Build Coastguard Worker    public Named build() {
403*1c2bbba8SAndroid Build Coastguard Worker      if (!getNickname().isPresent()) {
404*1c2bbba8SAndroid Build Coastguard Worker        setNickname(getName());
405*1c2bbba8SAndroid Build Coastguard Worker      }
406*1c2bbba8SAndroid Build Coastguard Worker      return autoBuild();
407*1c2bbba8SAndroid Build Coastguard Worker    }
408*1c2bbba8SAndroid Build Coastguard Worker  }
409*1c2bbba8SAndroid Build Coastguard Worker}
410*1c2bbba8SAndroid Build Coastguard Worker```
411*1c2bbba8SAndroid Build Coastguard Worker
412*1c2bbba8SAndroid Build Coastguard WorkerThe example illustrates having a package-private `autoBuild()` method that
413*1c2bbba8SAndroid Build Coastguard WorkerAutoBuilder implements. The public `build()` method calls it after adjusting the
414*1c2bbba8SAndroid Build Coastguard Workernickname if necessary.
415*1c2bbba8SAndroid Build Coastguard Worker
416*1c2bbba8SAndroid Build Coastguard WorkerThe builder in the example is an abstract class rather than an interface. An
417*1c2bbba8SAndroid Build Coastguard Workerabstract class allows us to distinguish between public methods for users of the
418*1c2bbba8SAndroid Build Coastguard Workerbuilder to call, and package-private methods that the builder's own logic uses.
419*1c2bbba8SAndroid Build Coastguard Worker
420*1c2bbba8SAndroid Build Coastguard Worker## Building annotation instances
421*1c2bbba8SAndroid Build Coastguard Worker
422*1c2bbba8SAndroid Build Coastguard WorkerAutoBuilder can build instances of annotation interfaces. When the annotation
423*1c2bbba8SAndroid Build Coastguard Workerhas no elements (methods in the annotation), or only one, then AutoAnnotation is
424*1c2bbba8SAndroid Build Coastguard Workersimpler to use. But when there are several elements, a builder is helpful. See
425*1c2bbba8SAndroid Build Coastguard Worker[here](howto.md#annotation) for examples of both.
426*1c2bbba8SAndroid Build Coastguard Worker
427*1c2bbba8SAndroid Build Coastguard Worker## Naming conventions
428*1c2bbba8SAndroid Build Coastguard Worker
429*1c2bbba8SAndroid Build Coastguard WorkerA setter method for the parameter `foo` can be called either `setFoo` or `foo`.
430*1c2bbba8SAndroid Build Coastguard WorkerA getter method can be called either `getFoo` or `foo`, and for a `boolean`
431*1c2bbba8SAndroid Build Coastguard Workerparameter it can also be called `isFoo`. The choice for getters and setters is
432*1c2bbba8SAndroid Build Coastguard Workerindependent. For example your getter might be `foo()` while your setter is
433*1c2bbba8SAndroid Build Coastguard Worker`setFoo(T)`.
434*1c2bbba8SAndroid Build Coastguard Worker
435*1c2bbba8SAndroid Build Coastguard WorkerBy convention, the parameter name of a setter method either echoes the parameter
436*1c2bbba8SAndroid Build Coastguard Workerbeing set:<br>
437*1c2bbba8SAndroid Build Coastguard Worker`Builder setName(String name);`<br>
438*1c2bbba8SAndroid Build Coastguard Workeror it is just `x`:<br>
439*1c2bbba8SAndroid Build Coastguard Worker`Builder setName(String x);`<br>
440*1c2bbba8SAndroid Build Coastguard Worker
441*1c2bbba8SAndroid Build Coastguard WorkerIf class `Foo` has a nested `@AutoBuilder` that builds instances of `Foo`, then
442*1c2bbba8SAndroid Build Coastguard Workerconventionally that type is called `Builder`, and instances of it are obtained
443*1c2bbba8SAndroid Build Coastguard Workerby calling a static `Foo.builder()` method:
444*1c2bbba8SAndroid Build Coastguard Worker
445*1c2bbba8SAndroid Build Coastguard Worker```java
446*1c2bbba8SAndroid Build Coastguard WorkerFoo foo1 = Foo.builder().setBar(bar).setBaz(baz).build();
447*1c2bbba8SAndroid Build Coastguard WorkerFoo.Builder fooBuilder = Foo.builder();
448*1c2bbba8SAndroid Build Coastguard Worker```
449*1c2bbba8SAndroid Build Coastguard Worker
450*1c2bbba8SAndroid Build Coastguard WorkerIf an `@AutoBuilder` for `Foo` is its own top-level class then that class will
451*1c2bbba8SAndroid Build Coastguard Workertypically be called `FooBuilder` and it will have a static `fooBuilder()` method
452*1c2bbba8SAndroid Build Coastguard Workerthat returns an instance of `FooBuilder`. That way callers can statically import
453*1c2bbba8SAndroid Build Coastguard Worker`FooBuilder.fooBuilder` and just write `fooBuilder()` in their code.
454*1c2bbba8SAndroid Build Coastguard Worker
455*1c2bbba8SAndroid Build Coastguard Worker```java
456*1c2bbba8SAndroid Build Coastguard Worker@AutoBuilder(ofClass = Foo.class)
457*1c2bbba8SAndroid Build Coastguard Workerpublic abstract class FooBuilder {
458*1c2bbba8SAndroid Build Coastguard Worker  public static FooBuilder fooBuilder() {
459*1c2bbba8SAndroid Build Coastguard Worker    return new AutoBuilder_FooBuilder();
460*1c2bbba8SAndroid Build Coastguard Worker  }
461*1c2bbba8SAndroid Build Coastguard Worker  ...
462*1c2bbba8SAndroid Build Coastguard Worker  public abstract Foo build();
463*1c2bbba8SAndroid Build Coastguard Worker}
464*1c2bbba8SAndroid Build Coastguard Worker```
465*1c2bbba8SAndroid Build Coastguard Worker
466*1c2bbba8SAndroid Build Coastguard WorkerIf an `@AutoBuilder` is designed to call a static method that is not a factory
467*1c2bbba8SAndroid Build Coastguard Workermethod, the word "call" is better than "build" in the name of the type
468*1c2bbba8SAndroid Build Coastguard Worker(`FooCaller`), the static method (`fooCaller()`), and the "build" method (`call()`).
469*1c2bbba8SAndroid Build Coastguard Worker
470*1c2bbba8SAndroid Build Coastguard Worker```java
471*1c2bbba8SAndroid Build Coastguard Worker@AutoBuilder(callMethod = "log", ofClass = MyLogger.class)
472*1c2bbba8SAndroid Build Coastguard Workerpublic abstract class LogCaller {
473*1c2bbba8SAndroid Build Coastguard Worker  public static LogCaller logCaller() {
474*1c2bbba8SAndroid Build Coastguard Worker    return new AutoBuilder_LogCaller();
475*1c2bbba8SAndroid Build Coastguard Worker  }
476*1c2bbba8SAndroid Build Coastguard Worker  ...
477*1c2bbba8SAndroid Build Coastguard Worker  public abstract void call();
478*1c2bbba8SAndroid Build Coastguard Worker}
479*1c2bbba8SAndroid Build Coastguard Worker
480*1c2bbba8SAndroid Build Coastguard Worker// used as:
481*1c2bbba8SAndroid Build Coastguard WorkerlogCaller().setLevel(Level.INFO).setMessage("oops").call();
482*1c2bbba8SAndroid Build Coastguard Worker```
483*1c2bbba8SAndroid Build Coastguard Worker
484*1c2bbba8SAndroid Build Coastguard Worker## Other builder features
485*1c2bbba8SAndroid Build Coastguard Worker
486*1c2bbba8SAndroid Build Coastguard WorkerThere are a number of other builder features that have not been detailed here
487*1c2bbba8SAndroid Build Coastguard Workerbecause they are the same as for `@AutoValue.Builder`. They include:
488*1c2bbba8SAndroid Build Coastguard Worker
489*1c2bbba8SAndroid Build Coastguard Worker*   [Special treatment of collections](builders-howto.md#collection)
490*1c2bbba8SAndroid Build Coastguard Worker*   [Handling of nested builders](builders-howto.md#nested_builders)
491*1c2bbba8SAndroid Build Coastguard Worker
492*1c2bbba8SAndroid Build Coastguard Worker## When parameter names are unavailable
493*1c2bbba8SAndroid Build Coastguard Worker
494*1c2bbba8SAndroid Build Coastguard WorkerAutoBuilder depends on knowing the names of parameters. But parameter names are
495*1c2bbba8SAndroid Build Coastguard Workernot always available in Java. They _are_ available in these cases, at least:
496*1c2bbba8SAndroid Build Coastguard Worker
497*1c2bbba8SAndroid Build Coastguard Worker*   In code that is being compiled at the same time as the `@AutoBuilder` class
498*1c2bbba8SAndroid Build Coastguard Worker    or interface.
499*1c2bbba8SAndroid Build Coastguard Worker*   In _records_ (from Java 16 onwards).
500*1c2bbba8SAndroid Build Coastguard Worker*   In the constructors of Kotlin data classes.
501*1c2bbba8SAndroid Build Coastguard Worker*   In code that was compiled with the [`-parameters`] option.
502*1c2bbba8SAndroid Build Coastguard Worker
503*1c2bbba8SAndroid Build Coastguard WorkerA Java compiler bug means that parameter names are not available to AutoBuilder
504*1c2bbba8SAndroid Build Coastguard Workerwhen compiling with JDK versions before 11, in any of these cases except the
505*1c2bbba8SAndroid Build Coastguard Workerfirst. We recommend building with a recent JDK, using the `--release` option if
506*1c2bbba8SAndroid Build Coastguard Workernecessary to produce code that can run on earlier versions.
507*1c2bbba8SAndroid Build Coastguard Worker
508*1c2bbba8SAndroid Build Coastguard WorkerIf parameter names are unavailable, you always have the option of introducing a
509*1c2bbba8SAndroid Build Coastguard Workerstatic method in the same class as the `@AutoBuilder` type, and having it call
510*1c2bbba8SAndroid Build Coastguard Workerthe method you want. Since it is compiled at the same time, its parameter names
511*1c2bbba8SAndroid Build Coastguard Workerare available.
512*1c2bbba8SAndroid Build Coastguard Worker
513*1c2bbba8SAndroid Build Coastguard WorkerHere's an example of fixing a problem this way. The code here typically will not
514*1c2bbba8SAndroid Build Coastguard Workercompile, since parameter names of JDK methods are not available:
515*1c2bbba8SAndroid Build Coastguard Worker
516*1c2bbba8SAndroid Build Coastguard Worker```java
517*1c2bbba8SAndroid Build Coastguard Workerimport java.time.LocalTime;
518*1c2bbba8SAndroid Build Coastguard Worker
519*1c2bbba8SAndroid Build Coastguard Workerpublic class TimeUtils {
520*1c2bbba8SAndroid Build Coastguard Worker  // Does not work, since parameter names from LocalTime.of are unavailable.
521*1c2bbba8SAndroid Build Coastguard Worker  @AutoBuilder(callMethod = "of", ofClass = LocalTime.class)
522*1c2bbba8SAndroid Build Coastguard Worker  public interface TimeBuilder {
523*1c2bbba8SAndroid Build Coastguard Worker    TimeBuilder setHour(int x);
524*1c2bbba8SAndroid Build Coastguard Worker    TimeBuilder setMinute(int x);
525*1c2bbba8SAndroid Build Coastguard Worker    TimeBuilder setSecond(int x);
526*1c2bbba8SAndroid Build Coastguard Worker    LocalTime build();
527*1c2bbba8SAndroid Build Coastguard Worker  }
528*1c2bbba8SAndroid Build Coastguard Worker}
529*1c2bbba8SAndroid Build Coastguard Worker```
530*1c2bbba8SAndroid Build Coastguard Worker
531*1c2bbba8SAndroid Build Coastguard WorkerIt will produce an error message like this:
532*1c2bbba8SAndroid Build Coastguard Worker
533*1c2bbba8SAndroid Build Coastguard Worker```
534*1c2bbba8SAndroid Build Coastguard Workererror: [AutoBuilderNoMatch] Property names do not correspond to the parameter names of any static method named "of":
535*1c2bbba8SAndroid Build Coastguard Worker  public interface TimeBuilder {
536*1c2bbba8SAndroid Build Coastguard Worker  ^
537*1c2bbba8SAndroid Build Coastguard Worker    of(int arg0, int arg1)
538*1c2bbba8SAndroid Build Coastguard Worker    of(int arg0, int arg1, int arg2)
539*1c2bbba8SAndroid Build Coastguard Worker    of(int arg0, int arg1, int arg2, int arg3)
540*1c2bbba8SAndroid Build Coastguard Worker```
541*1c2bbba8SAndroid Build Coastguard Worker
542*1c2bbba8SAndroid Build Coastguard WorkerThe names `arg0`, `arg1`, etc are concocted by the compiler because it doesn't
543*1c2bbba8SAndroid Build Coastguard Workerhave the real names.
544*1c2bbba8SAndroid Build Coastguard Worker
545*1c2bbba8SAndroid Build Coastguard WorkerIntroducing a static method fixes the problem:
546*1c2bbba8SAndroid Build Coastguard Worker
547*1c2bbba8SAndroid Build Coastguard Worker```java
548*1c2bbba8SAndroid Build Coastguard Workerimport java.time.LocalTime;
549*1c2bbba8SAndroid Build Coastguard Worker
550*1c2bbba8SAndroid Build Coastguard Workerpublic class TimeUtils {
551*1c2bbba8SAndroid Build Coastguard Worker  static LocalTime localTimeOf(int hour, int minute, int second) {
552*1c2bbba8SAndroid Build Coastguard Worker    return LocalTime.of(hour, minute, second);
553*1c2bbba8SAndroid Build Coastguard Worker  }
554*1c2bbba8SAndroid Build Coastguard Worker
555*1c2bbba8SAndroid Build Coastguard Worker  @AutoBuilder(callMethod = "localTimeOf")
556*1c2bbba8SAndroid Build Coastguard Worker  public interface TimeBuilder {
557*1c2bbba8SAndroid Build Coastguard Worker    TimeBuilder setHour(int x);
558*1c2bbba8SAndroid Build Coastguard Worker    TimeBuilder setMinute(int x);
559*1c2bbba8SAndroid Build Coastguard Worker    TimeBuilder setSecond(int x);
560*1c2bbba8SAndroid Build Coastguard Worker    LocalTime build();
561*1c2bbba8SAndroid Build Coastguard Worker  }
562*1c2bbba8SAndroid Build Coastguard Worker}
563*1c2bbba8SAndroid Build Coastguard Worker```
564*1c2bbba8SAndroid Build Coastguard Worker
565*1c2bbba8SAndroid Build Coastguard Worker[`-parameters`]: https://docs.oracle.com/en/java/javase/16/docs/specs/man/javac.html#option-parameters
566