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