When to Use Constructors, JavaBeans, or Builders in Java?
This article compares three Java object‑creation techniques—telescoping constructors, the JavaBean pattern, and the Builder pattern—explaining their advantages, drawbacks, code examples, and when each approach is most appropriate for scalable and readable code.
1. Introduction
When dealing with Java classes that have many optional member variables, there are three main ways to create objects: telescoping constructors, the JavaBean pattern, and the Builder pattern.
2. Constructors
UserInfo userInfo1 = new UserInfo("felord.cn", 28);
UserInfo xxxxxx = new UserInfo("felord.cn", "xxxxxx", 28);
UserInfo xxxxxx1 = new UserInfo("felord.cn", "xxxxxx", 28, LocalDateTime.now());Constructors often need overloads for scalability; sometimes null is passed for optional parameters, which makes the meaning of arguments unclear and can cause errors, such as swapping username and address without triggering a compile‑time failure.
If a parameter list becomes long (seven or eight items), the code becomes verbose. Nevertheless, constructors are still valuable, especially for creating immutable objects.
3. JavaBean
The most common way to create an object is to use a no‑arg constructor and then set each field via setter methods.
UserInfo userInfo = new UserInfo();
userInfo.setUsername("felord.cn");
userInfo.setAge(28);Many frameworks such as Jackson, Spring Framework, and most ORM libraries rely on this pattern. It works in most cases but requires two steps and cannot create immutable objects.
4. Builder
The Builder pattern, used for example in Spring Security's HttpSecurity configuration, provides the safety of telescoping constructors with better readability.
A static inner Builder class holds the same fields and offers fluent setter methods that return the builder itself, ending with a build() method that creates the target object.
public class UserInfo {
private String username;
private String address;
private Integer age;
private LocalDateTime addTime;
// private no‑arg constructor
private UserInfo() {}
public static class Builder {
private String username;
private String address;
private Integer age;
private LocalDateTime addTime;
public Builder username(String username) { this.username = username; return this; }
public Builder address(String address) { this.address = address; return this; }
public Builder age(Integer age) { this.age = age; return this; }
public Builder addTime(LocalDateTime addTime) { this.addTime = addTime; return this; }
public UserInfo build() {
UserInfo userInfo = new UserInfo();
userInfo.username = this.username;
userInfo.address = this.address;
userInfo.age = this.age;
userInfo.addTime = this.addTime;
return userInfo;
}
}
// getters omitted
}Usage example:
UserInfo userInfo = new UserInfo.Builder()
.username("felord.cn")
.address("xxxxxx")
.age(28)
.addTime(LocalDateTime.now())
.build();This approach yields fluent, readable code and handles optional parameters well, though it adds extra boilerplate. Lombok's @Builder annotation can generate the pattern automatically, but not everyone prefers Lombok.
5. Summary
In everyday Java development, constructors and JavaBeans are the most common ways to create objects, while the Builder pattern is useful for configuration objects and when you need immutable instances.
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.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
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.
