From 1b66450566b04567c6c6dfd7a68585ebd427fe49 Mon Sep 17 00:00:00 2001 From: mjaggard Date: Fri, 1 Dec 2023 11:06:31 +0000 Subject: [PATCH] Explain builder default gotchas --- website/templates/features/Builder.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/website/templates/features/Builder.html b/website/templates/features/Builder.html index 1461161fb2..b7a4f2e2ba 100644 --- a/website/templates/features/Builder.html +++ b/website/templates/features/Builder.html @@ -66,7 +66,7 @@

Now that the "method" mode is clear, putting a @Builder annotation on a constructor functions similarly; effectively, constructors are just static methods that have a special syntax to invoke them: Their 'return type' is the class they construct, and their type parameters are the same as the type parameters of the class itself.

- Finally, applying @Builder to a class is as if you added @AllArgsConstructor(access = AccessLevel.PACKAGE) to the class and applied the @Builder annotation to this all-args-constructor. This only works if you haven't written any explicit constructors yourself. If you do have an explicit constructor, put the @Builder annotation on the constructor instead of on the class. Note that if you put both `@Value` and `@Builder` on a class, the package-private constructor that `@Builder` wants to generate 'wins' and suppresses the constructor that `@Value` wants to make. + Finally, applying @Builder to a class is as if you added @AllArgsConstructor(access = AccessLevel.PACKAGE) to the class and applied the @Builder annotation to this all-args-constructor. This only works if you haven't written any explicit constructors yourself or created one with @NoArgsConstructor. If you do have an explicit constructor, put the @Builder annotation on the constructor instead of on the class. Note that if you put both `@Value` and `@Builder` on a class, the package-private constructor that `@Builder` wants to generate 'wins' and suppresses the constructor that `@Value` wants to make.

If using @Builder to generate builders to produce instances of your own class (this is always the case unless adding @Builder to a method that doesn't return your own type), you can use @Builder(toBuilder = true) to also generate an instance method in your class called toBuilder(); it creates a new builder that starts out with all the values of this instance. You can put the @Builder.ObtainVia annotation on the parameters (in case of a constructor or method) or fields (in case of @Builder on a type) to indicate alternative means by which the value for that field/parameter is obtained from this instance. For example, you can specify a method to be invoked: @Builder.ObtainVia(method = "calculateFoo").

@@ -100,7 +100,8 @@

@Builder.Default

If a certain field/parameter is never set during a build session, then it always gets 0 / null / false. If you've put @Builder on a class (and not a method or constructor) you can instead specify the default directly on the field, and annotate the field with @Builder.Default:
- @Builder.Default private final long created = System.currentTimeMillis(); + @Builder.Default private final long created = System.currentTimeMillis();
+ Calling Lombok-generated constructors such as @NoArgsConstructor will also make use of the defaults specified using @Builder.Default however explicit constructors will no longer use the default values and will need to be set manually or call a Lombok-generated constructor such as this(); to set the defaults.