Skip to content

Commit

Permalink
Merge pull request #3560 from mjaggard/patch-2
Browse files Browse the repository at this point in the history
Explain builder default gotchas
  • Loading branch information
rzwitserloot authored Jan 11, 2024
2 parents 0089374 + 1b66450 commit 9d9df38
Showing 1 changed file with 3 additions and 2 deletions.
5 changes: 3 additions & 2 deletions website/templates/features/Builder.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
</p><p>
Now that the "method" mode is clear, putting a <code>@Builder</code> 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.
</p><p>
Finally, applying <code>@Builder</code> to a class is as if you added <code>@AllArgsConstructor(access = AccessLevel.PACKAGE)</code> to the class and applied the <code>@Builder</code> 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 <code>@Builder</code> 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 <code>@Builder</code> to a class is as if you added <code>@AllArgsConstructor(access = AccessLevel.PACKAGE)</code> to the class and applied the <code>@Builder</code> 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 <code>@Builder</code> 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.
</p><p>
If using <code>@Builder</code> to generate builders to produce instances of your own class (this is always the case unless adding <code>@Builder</code> to a method that doesn't return your own type), you can use <code>@Builder(toBuilder = true)</code> to also generate an instance method in your class called <code>toBuilder()</code>; it creates a new builder that starts out with all the values of this instance. You can put the <code>@Builder.ObtainVia</code> annotation on the parameters (in case of a constructor or method) or fields (in case of <code>@Builder</code> 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: <code>@Builder.ObtainVia(method = "calculateFoo")</code>.
</p><p>
Expand Down Expand Up @@ -100,7 +100,8 @@ <h3 id="builderdefault"><a name="builderdefault">@Builder.Default</a></h3>

<p>
If a certain field/parameter is never set during a build session, then it always gets 0 / <code>null</code> / false. If you've put <code>@Builder</code> on a class (and not a method or constructor) you can instead specify the default directly on the field, and annotate the field with <code>@Builder.Default</code>:<br />
<code>@Builder.Default private final long created = System.currentTimeMillis();</code>
<code>@Builder.Default private final long created = System.currentTimeMillis();</code><br/>
Calling Lombok-generated constructors such as <code>@NoArgsConstructor</code> will also make use of the defaults specified using <code>@Builder.Default</code> 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 <code>this();</code> to set the defaults.
</p>
</@f.featureSection>

Expand Down

0 comments on commit 9d9df38

Please sign in to comment.