@Builder

Since

@Builder was introduced as experimental feature in lombok v0.11.10.

Experimental

Experimental because:

  • New feature - community feedback requested.
  • This feature will move to the core package soon.
Current status: sure thing - This feature will move to the core package soon.

Overview

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:

  • An inner static class named FooBuilder, with the same type arguments as the static method (called the builder).
  • In the builder: One private non-static non-final field for each parameter of the target.
  • In the builder: A package private no-args empty constructor.
  • In the builder: A 'setter'-like method for each parmeter of the target: It has the same type as that parameter and the same name. It returns the builder itself, so that the setter calls can be chained, as in the above example.
  • In the builder: A build() method which calls the static method, passing in each field. It returns the same type that the target returns.
  • In the builder: A sensible toString() implementation.
  • In the class containing the target: A builder() method, which creates a new instance of the builder.
Each listed generated element will be silently skipped if that element already exists (disregarding parameter counts and looking only at names). This includes the builder itself: If that class already exists, lombok will simply start injecting fields and methods inside this already existing class, unless of course the fields / methods to be injected already exist.

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")

With Lombok

@HTML_PRE@

Vanilla Java

@HTML_POST@

Small print

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.