If I add @Builder to a class. The builder method is created.
Person.builder().name(\"john\").surname(\"Smith\").build();
I have a requirem
I would recommend against this approach, as you will struggle to apply it consistently on other objects. Instead, you can just mark fields with @lombok.NonNull annotation and Lombok will generate null checks for you in the constructor and setters, so that Builder.build() will fail, if those fields are not set.
Using builder pattern allows you to have very clear identification of which fields you're setting to which values. This is already lost for name field in your example, and it will further be lost for all other required fields, if you're building an object with multiple required fields. Consider the following example, can you tell which field is which just by reading code?
Person.builder("John", "Michael", 16, 1987) // which is name, which is surname? what is 16?
.year(1982) // if this is year of birth, then what is 1987 above?
.build()
Taking Kevin Day's answer a step further:
@Builder
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE) // If immutability is desired
@ToString
public class Person {
@NonNull // Presumably name cannot be null since its required by the builder
private final String name;
private final String surname;
private static PersonBuilder builder() {
return new PersonBuilder();
}
public static PersonBuilder builder(String name){
return builder().name(name);
}
}
It's not ideal, but it provides compile time enforcement and callers of this class will have exactly one builder method to use.
Combining the answer from @Pawel and comment from Max ...
import lombok.Builder;
import lombok.ToString;
@Builder
public class Person {
private String name;
private String surname;
public static PersonBuilder builder(String name) {
return new PersonBuilder().name(name);
}
}
Here's another approach:
@Builder()
@Getter
@ToString
public class Person {
private final String name;
private final String surname;
public static PersonBuilder builder(String name){
return new PersonBuilder().name(name);
}
public static void main(String[] args) {
Person p = Person.builder("John Doe")
.surname("Bill")
.build();
}
}
You can do it easily with Lombok annotation configuration
import lombok.Builder;
import lombok.ToString;
@Builder(builderMethodName = "hiddenBuilder")
@ToString
public class Person {
private String name;
private String surname;
public static PersonBuilder builder(String name) {
return hiddenBuilder().name(name);
}
}
And then use it like that
Person p = Person.builder("Name").surname("Surname").build();
System.out.println(p);
Of course @ToString is optional here.
Take User class as example, id field is required:
@AllArgsConstructor(access = AccessLevel.PRIVATE) // required, see https://stackoverflow.com/questions/51122400/why-is-lombok-builder-not-compatible-with-this-constructor
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
@Getter
public class User {
private String id;
private String name;
private int age;
public static UserBuilder builder(final String id) {
return new UserBuilder().id(id);
}
}
You can only initialize a User instance by builder like User user = User.builder("id-123").name("Tom").build;. With private no args constructer, you are not able to User user = new User(); or User user = new User("id-123"); so you always need to pass the required parameter id. Please note the initialized instance is immutable.