Is there any way to automate writing Builder patterns in IntelliJ?
For example, given this simple class:
class Film {
private String title;
private
If you are wondering if this can be used to create a class with an inner builder class as described by Joshua Block - you just have to define an empty inner class first, then check "Use existing" and search for your newly created (inner class) and hit "Refactor".
PS! Cursor must reside inside constructor (pre-written) in order to use the "Replace Constructor with Builder" refactoring function.
For those wanting to replace "too many parameters" with a builder pattern, do "extract parameter object" and then the convert constructor to builder mentioned in other answers here.
I found the built-in builder pattern generation in IntelliJ to be a bit clunky for a few reasons:
command+N
on OS X).The InnerBuilder plugin addresses all of these shortcomings, and requires no setup or configuration. Here's a sample Builder generated by the plugin:
public class Person {
private String firstName;
private String lastName;
private int age;
private Person(Builder builder) {
firstName = builder.firstName;
lastName = builder.lastName;
age = builder.age;
}
public static final class Builder {
private String firstName;
private String lastName;
private int age;
public Builder() {
}
public Builder firstName(String firstName) {
this.firstName = firstName;
return this;
}
public Builder lastName(String lastName) {
this.lastName = lastName;
return this;
}
public Builder age(int age) {
this.age = age;
return this;
}
public Person build() {
return new Person(this);
}
}
}
The IntelliJ way to to this is, IMHO, is convoluted. There are out there two plugins (I prefer this one: https://plugins.jetbrains.com/plugin/7354) that serve the purpose much much better.
For example, I prefer having the Builder class as an inner class of the PoJo. To achieve that with IntelliJ you need few extra strokes.
Another plus for the plugin is the location of the functionality (in the Generate...
context menu).
In my opinion, the simplest way to get the inner static class instead of a separate are:
Lombok is the easiest way to do it! (It has a Intellij plugin for syntax support https://plugins.jetbrains.com/plugin/6317-lombok-plugin)
Just add a @Builder
annotation, and behind the walls it will add a builder implementation inside the object.
With Lombok:
import lombok.Builder;
import lombok.Singular;
import java.util.Set;
@Builder
public class BuilderExample {
@Builder.Default private long created = System.currentTimeMillis();
private String name;
private int age;
@Singular private Set<String> occupations;
}
Without Lombok:
import java.util.Set;
public class BuilderExample {
private long created;
private String name;
private int age;
private Set<String> occupations;
BuilderExample(String name, int age, Set<String> occupations) {
this.name = name;
this.age = age;
this.occupations = occupations;
}
private static long $default$created() {
return System.currentTimeMillis();
}
public static BuilderExampleBuilder builder() {
return new BuilderExampleBuilder();
}
public static class BuilderExampleBuilder {
private long created;
private boolean created$set;
private String name;
private int age;
private java.util.ArrayList<String> occupations;
BuilderExampleBuilder() {
}
public BuilderExampleBuilder created(long created) {
this.created = created;
this.created$set = true;
return this;
}
public BuilderExampleBuilder name(String name) {
this.name = name;
return this;
}
public BuilderExampleBuilder age(int age) {
this.age = age;
return this;
}
public BuilderExampleBuilder occupation(String occupation) {
if (this.occupations == null) {
this.occupations = new java.util.ArrayList<String>();
}
this.occupations.add(occupation);
return this;
}
public BuilderExampleBuilder occupations(Collection<? extends String> occupations) {
if (this.occupations == null) {
this.occupations = new java.util.ArrayList<String>();
}
this.occupations.addAll(occupations);
return this;
}
public BuilderExampleBuilder clearOccupations() {
if (this.occupations != null) {
this.occupations.clear();
}
return this;
}
public BuilderExample build() {
// complicated switch statement to produce a compact properly sized immutable set omitted.
Set<String> occupations = ...;
return new BuilderExample(created$set ? created : BuilderExample.$default$created(), name, age, occupations);
}
@java.lang.Override
public String toString() {
return "BuilderExample.BuilderExampleBuilder(created = " + this.created + ", name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")";
}
}
}
Source: https://projectlombok.org/features/Builder