静态内部类在Builder模式中用于解耦构造逻辑,避免非静态内部类隐式持有外部实例导致的内存泄漏与生命周期依赖,支持链式调用、必填参数编译期校验及不可变对象构建。

静态内部类在 Builder 模式中构建复杂对象,本质是把构造逻辑从主类中解耦出来,用一个独立、无外部引用的工具类来控制创建流程。它不靠语法糖,而靠设计约束实现清晰、安全、可维护的对象组装。
为什么必须用静态内部类
非静态内部类会隐式持有外部类实例引用,而 Builder 在 build 之前根本不需要那个实例——既浪费内存,又可能造成意外的生命周期依赖。静态内部类完全独立,语义上更贴合“工厂”定位,也天然支持访问外部类的私有字段(配合私有构造器即可)。
- 避免隐式引用导致的内存泄漏风险
- 确保 Builder 实例可被自由创建、丢弃,不受外部对象生命周期牵制
- 编译期就能识别其工具属性,便于 IDE 提示和代码审查
核心结构怎么搭
Builder 类内部要镜像目标类的关键字段,但只用于暂存;所有 setter 返回 this 实现链式调用;build() 方法统一校验并触发私有构造。
- 字段声明为 private,不暴露 getter,防止外部读取中间状态
- 每个 setter 方法形如 public Builder cpu(String cpu) { this.cpu = cpu; return this; }
- build() 中先校验必填项(如为空抛 IllegalArgumentException),再 new 目标对象
- 目标类构造器必须 private,字段全部 final,杜绝后续修改
必填项与默认值怎么处理
真正严谨的做法,是把必填参数塞进 Builder 的构造器里,而不是靠 build() 时检查——这样能在编译期拦截缺失关键信息的调用。
立即学习“Java免费学习笔记(深入)”;
- 例如 Email.Builder(String to, String subject, String body),强制传入三要素
- 可选字段(如附件列表、抄送人)通过 setter 提供,默认值可在构造器中初始化:this.attachments = new ArrayList()
- 复杂默认逻辑(如生成 UUID、设当前时间)放在 build() 内执行,避免提前计算或重复触发
容易踩的坑有哪些
几个看似小、却直接影响健壮性的细节:
- 每次调用 builder() 方法必须返回新 Builder 实例,否则多个链式调用会共享状态,互相污染
- build() 后应清空 Builder 内部状态(或设计为一次性使用),避免误复用
- 不要在 Builder 中暴露任何字段的 public getter,它只是临时容器,不是数据载体
- 校验逻辑要集中且明确——比如邮箱格式、数值范围、字符串非空等,失败统一抛 IllegalArgumentException


















