链式调用 builder.seta().setb() 的本质是每个 setter 方法返回当前对象的 this 引用,全程操作同一堆内存实例,无新对象创建,字节码层面通过栈上引用流转实现零额外内存分配。

链式调用 builder.setA().setB() 的底层引用流转,本质是“返回当前对象的引用”,整个过程不创建新对象,所有方法操作的都是同一个实例在堆中的地址。
每次调用都返回同一个对象的 this 引用
每个 setter 方法(如 setA()、setB())末尾都写有 return this;。这里的 this 是当前对象在堆内存中的真实引用(即地址),不是副本,也不是新对象。JVM 直接把这个引用值作为方法的返回值,供下一次点号调用使用。
-
builder.setA()执行后,修改自身字段,并把 builder 自己的引用返回 - 该返回值立即成为
.setB()的调用主体,也就是还是原来的 builder 实例 - 整个链条中,对象只有一份,引用始终指向同一块堆内存
与普通 void 方法的关键区别
如果方法声明为 void setA(),调用完就“丢掉”了 builder 引用,无法继续点操作;而返回 Builder 类型(实际是 return this),相当于把“接力棒”稳稳交到下一个方法手上。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 返回类型必须是当前类(或其子类),不能是
void或无关类型 - 不能返回新对象(如
return new Builder().setA(...)),否则会中断引用连续性 - 返回
this是浅层引用传递,不是复制对象,也没有拷贝开销
字节码层面:只是连续压栈和调用
编译后,builder.setA().setB() 对应的字节码类似:
- 先将 builder 引用压入操作数栈
- 调用
setA(),方法内部修改字段,再把栈顶的 this 引用原样返回并留在栈顶 - 接着直接用栈顶这个引用调用
setB(),无需重新加载 builder 变量
整个过程没有中间变量、没有临时对象,纯粹靠引用在栈上“流转”。这也是链式调用零额外内存分配的原因。
注意不可变场景下的例外
如果设计成不可变风格(比如每次 setA() 都返回新对象),那引用就变了——但这就不是传统意义上的 this 链式调用,而是函数式风格的复制构造。真正的 this 链式调用默认是可变的,且依赖对象状态被就地修改。
- Builder 模式常用可变方式,因为构建过程本就是逐步赋值
- 若需线程安全或避免副作用,应配合同步、不可变字段或构建完成后的冻结机制
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










