Why You Should Stop Using Lombok’s @Builder and What to Use Instead
This article explains the hidden pitfalls of Lombok’s @Builder annotation, why it often violates the Builder pattern, and presents @Accessors and manual fluent setters as safer, more flexible alternatives for Java backend development.
In the article "Oh!! Stop using @Builder", the author points out a major pitfall of Lombok’s @Builder annotation where default values are lost, and explains why @Builder often misleads developers into thinking it follows the Builder pattern.
1. Reproducing the scenario
1.1 Without @Builder
Class definition:
package io.gitrebase.demo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class APIResponse<T> {
private T payload;
private Status status;
}Usage example:
package io.gitrebase.demo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@Slf4j
@RestControllerAdvice(assignableTypes = io.gitrebase.demo.RestApplication.class)
public class ApplicationExceptionHandler {
@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
public APIResponse handleException(Exception exception) {
log.error("Unhandled Exception", exception);
Status status = new Status();
status.setResponseCode("RESPONSE_CODE_IDENTIFIER");
status.setDescription("Bla Bla Bla");
APIResponse response = new APIResponse();
response.setStatus(status);
return response;
}
}1.2 Using @Builder
Class definition:
package io.gitrebase.demo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class APIResponse<T> {
private T payload;
private Status status;
}Usage example:
package io.gitrebase.demo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@Slf4j
@RestControllerAdvice(basePackageClasses = io.gitrebase.demo.RestApplication.class)
public class ApplicationExceptionHandler {
@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
public APIResponse handleException(Exception exception) {
log.error("Unhandled Exception", exception);
return APIResponse.builder()
.status(Status.builder()
.responseCode("RESPONSE_CODE_IDENTIFIER")
.description("Bla Bla Bla")
.build())
.build();
}
}2. Why @Builder is not recommended
@Builder generates a mutable builder that cannot distinguish required from optional parameters, violates immutability, and is limited to a concrete type, which defeats the purpose of the Builder pattern.
3. Alternatives
3.1 Prefer @Accessors
Class definition with @Accessors(chain = true):
package io.gitrebase.demo;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class APIResponse<T> {
private T payload;
private Status status;
}The compiled class shows fluent setters returning the object itself.
3.2 Manual simulation of @Accessors
When @Accessors is unavailable, you can write explicit fluent setters or use a constructor for required fields and chain optional setters.
// Example Person class
@Getter
@Accessors(chain = true)
public class Person {
private String name; // required
private int id; // required
private int age; // optional
private String address; // optional
public Person(String name, int id) {
this.name = name;
this.id = id;
}
}
// Usage
Person person = new Person("Zhang San", 1001)
.setAge(25)
.setAddress("Beijing");
System.out.println(person);4. Takeaways
Most developers use Lombok annotations without inspecting the generated code. Understanding the underlying implementation helps avoid hidden bugs. In many cases @Accessors provides a clearer, more flexible alternative to @Builder.
References
https://blog.csdn.net/w605283073/article/details/130190814
https://medium.com/gitrebase/oh-stop-using-builder-9061a5911d8c
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
