@Builder was introduced as experimental feature in lombok v0.12.0.
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.@EqualsAndHashCode
on the builder class.
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(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.
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 configurable aspects of builder are:
"build"
)"builder"
)fieldName()
, a non-fluent one is named setFieldName()
. (default: true
)void
. (default: true
)@Builder(builderClassName = "HelloWorldBuilder", buildMethodName = "execute", builderMethodName = "helloWorld", fluent = false, chain = false)
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.
If an explicit constructor is present, but @Builder
is placed on the class, then the builder will be generated as if an explicit constructor is present with the
same arguments list as what @AllArgsConstructor
would produce. If this constructor does not exist, a compile time error will result. Usually you should just either let
lombok make this constructor (delete your constructor from the source), or, move the @Builder
annotation to the constructor.