选static内部类是因为它不持有外部类实例引用,避免内存泄漏、支持无实例创建、语义更清晰;普通内部类隐式持外层引用,违背Builder单一职责。

Java 中用 static 内部类实现建造者模式,核心在于解耦构建逻辑与外部类、避免实例依赖、提升可读性和线程安全性。它比普通内部类更轻量,也比静态工具类更结构化。
为什么选 static 内部类而不是普通内部类?
普通非静态内部类隐式持有外部类实例引用,会导致:
- 内存泄漏风险(尤其在 Builder 持有长生命周期对象时)
- 无法在无外部类实例时创建 Builder(比如从静态工厂方法启动)
- 语义不清:Builder 本就不该依赖具体外部对象的状态
static 内部类切断了这种绑定,让 Builder 纯粹聚焦于构造过程,符合单一职责原则。
标准写法:嵌套 + 链式调用 + build() 封装
以构建一个不可变的 User 类为例:
立即学习“Java免费学习笔记(深入)”;
public class User {
private final String name;
private final int age;
private final String email;
private User(Builder builder) {
this.name = builder.name;
this.age = builder.age;
this.email = builder.email;
}
// static 内部 Builder 类
public static class Builder {
private String name;
private int age;
private String email;
public Builder name(String name) {
this.name = name;
return this; // 支持链式调用
}
public Builder age(int age) {
this.age = age;
return this;
}
public Builder email(String email) {
this.email = email;
return this;
}
public User build() {
// 可加校验逻辑,如:if (name == null) throw new IllegalStateException("name is required");
return new User(this);
}
}
}
使用方式简洁清晰:
User user = new User.Builder()
.name("Alice")
.age(30)
.email("alice@example.com")
.build();
进阶技巧:支持必填项约束与构建校验
仅靠链式调用无法强制某些字段必须设置。可通过分阶段 Builder 或构造函数参数强化约束:
- 将必填字段放入
Builder构造函数(如new Builder(String name)),确保初始化即存在 - 在
build()中执行空值/范围检查,抛出明确异常(如IllegalArgumentException) - 对敏感字段(如密码)做防御性拷贝或清理,避免外部修改影响最终对象
注意点:避免常见陷阱
不要在 Builder 中暴露可变对象引用 —— 若外部传入 List 或自定义对象,Builder 应深拷贝或不可变包装,防止后续修改污染构建结果。
Builder 实例不应被复用 —— 虽然语法上允许连续调用 build() 多次,但若 Builder 字段未重置,第二次 build() 可能返回错误状态的对象。建议每次新建 Builder 实例,或在 build() 后清空字段(需谨慎设计)。
考虑泛型支持 —— 如需构建带类型参数的对象,可将 Builder 声明为 public static class Builder<T>,并配合泛型方法链式调用。


















