@Builder was introduced as experimental feature in lombok v0.11.10.
Experimental because:
The @Builder
annotation produces complex builder APIs for your classes.
@Builder
lets you automatically produce the code required to have your class be instantiable with code such as:
Person.builder().name("Adam Savage").city("San Francisco").worksAt("Mythbusters").build();
@Builder
can be placed on a class, or on a constructor, or on a static method. While the "on a class" and "on a constructor"
mode are the most common use-case, @Builder
is most easily explained with the "static method" use-case.
A static method annotated with @Builder
(from now on called the target) causes the following 7 things to be generated:
FooBuilder
, with the same type arguments as the static method (called the builder).build()
method which calls the static method, passing in each field. It returns the same type that the
target returns.toString()
implementation.builder()
method, which creates a new instance of the builder.
Now that the "static 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(acces = AccessLevel.PACKAGE)
to the class and applied the
@Builder
annotation to this all-args-constructor. Note that this constructor is only generated if there is no explicit
constructor present in the so annotated class, but this @AllArgsConstructor
has priority over any other implicitly
generated lombok constructor (such as @Data
and @Value
). If an explicit constructor is present, no constructor is generated,
but the builder will be created with the assumption that this constructor exists. If you've written another constructor, you'll get a compilation error.
The solution is to either let lombok write this constructor (delete your own), or, annotate your constructor instead.
The name of the builder class is FoobarBuilder
, where Foobar is the simplified, title-cased form of the return type of the
target - that is, the name of your type for @Builder
on constructors and types, and the name of the return type for @Builder
on static methods. For example, if @Builder
is applied to a class named com.yoyodyne.FancyList<T>
, then the builder name will be
FancyListBuilder<T>
. If @Builder
is applied to a static method that returns void
, the builder will be named
VoidBuilder
.
The only configurable aspect of builder are the builder's class name (default: return type + 'Builder'), the build() method's name, and the
builder() method's name:
@Builder(builderClassName = "HelloWorldBuilder", buildMethodName = "execute", builderMethodName = "helloWorld")
Another strategy for fluent APIs is that the programmer using your library statically imports your 'builder' method. In this case, you might want to name your builder
method equal to your type's name. So, the builder method for a class called Person
would become person()
. This is nicer if the builder method
is statically imported.
If the return type of your target static method is a type parameter (such as T
), lombok will enforce an explicit builder class name.
You don't HAVE to use @Builder
to build anything; you can for example put it on a static method that has lots of parameter to improve the API of it.
In this case, we suggest you use buildMethodName =
to rename the build method to execute()
instead.
The builder class will NOT get an auto-generated implementation of hashCode
or equals
methods! These would suggest that it is sensible to use
instances of a builder as keys in a set or map. However, that's not a sensible thing to do. Hence, no hashCode
or equals
.
Generics are sorted out for you.