Self-Types模式是通过递归泛型边界(如T extends FluentBuilder<T>)使泛型类方法返回具体子类型以支持类型安全链式调用的设计技巧;它非Java原生语法,需子类显式传入自身类型,避免this或通配符导致的类型丢失。

什么是Self-Types模式
Self-Types模式是一种在泛型类中让方法返回当前具体类型(而非父类型或原始类型)的设计技巧,目的是支持真正的链式调用。它不是Java语言原生语法(如Scala中的self: T =>),而是通过泛型递归边界(recursive type bound)模拟实现:让类型参数继承自当前泛型类自身。
核心写法:递归泛型边界
关键在于定义泛型类时,用类型参数约束它必须是该类的子类型:
public abstract class FluentBuilder<T extends FluentBuilder<T>> {
public T setName(String name) {
// 设置逻辑
return (T) this;
}
public T setAge(int age) {
// 设置逻辑
return (T) this;
}
}
子类继承时需显式传入自身类型:
public class UserBuilder extends FluentBuilder<UserBuilder> {
private String name;
private int age;
@Override
public UserBuilder setName(String name) {
this.name = name;
return this; // 编译器知道这是UserBuilder,非FluentBuilder
}
public User build() {
return new User(name, age);
}
}
这样就能安全链式调用:new UserBuilder().setName("Alice").setAge(30).build(),全程保持UserBuilder类型。
为什么不能只用this或FluentBuilder<?>
直接返回this在父类中类型是FluentBuilder<T>,调用者无法继续调用子类特有方法;若返回FluentBuilder<?>则类型擦除后失去具体类型信息,链式中断。递归边界让编译器在子类实例化时“固定”了T为子类本身,从而实现类型精确推导。
实际使用注意事项
-
抽象基类建议设为
abstract:避免被直接实例化,强制用户继承并指定具体类型 - 构造函数和字段通常放在子类:基类聚焦通用行为(如日志、校验钩子),状态由子类管理
- 慎用多重继承场景:Java不支持多继承,若子类还需继承其他类,可考虑组合+委托替代
-
Lombok可简化:配合
@Accessors(chain = true)能自动生成链式setter,但失去类型安全控制,适合简单场景

















