要实现父子类都能链式调用的泛型构建者模式,核心是使用F-bound类型参数:父类Person

要实现父子类都能链式调用的泛型构建者模式(Generic Builder),核心是让子类构建者能返回自身类型,而不是父类构建者,避免类型擦除导致的链式中断。关键在于使用“F-bound type parameter”(自引用泛型)配合递归泛型定义。
父类构建者声明:用泛型参数绑定自身
父类 Person 及其构建者不直接写死返回类型,而是把构建者类型作为泛型参数传入,让子类能“回填”自己的构建者类型:
- 父类定义:
class Person<B extends Person.Builder<B>> - 构建者声明为抽象静态类,并带相同泛型参数:
abstract static class Builder<B extends Builder<B>> - 所有 setter 方法返回
B(即具体子类构建者),而非Builder
子类构建者继承并“回填”自身类型
子类(如 Student)继承父类时,显式将自身构建者类型传给父类泛型参数;其构建者继承父构建者,并把泛型参数设为自身:
class Student extends Person<Student.Builder>static class Builder extends Person.Builder<Builder>- 这样
name("Alice").grade(95)中,name()返回Builder,后续可继续调用子类特有方法
关键细节:避免类型丢失和编译错误
常见坑点及解法:
立即学习“Java免费学习笔记(深入)”;
- 构造器中必须调用
self()—— 父构建者里定义一个抽象方法protected abstract B self();,子构建者覆写为return (B) this; - 所有 setter 必须以
return self();结尾,保证返回的是当前构建者实例(而非父类类型) - 不要在父构建者中 new 子类实例;构建逻辑由子类
build()实现,父类build()应为protected abstract T build();
完整最小示例(可直接运行)
以下代码体现父子链式调用:new Student.Builder().name("Tom").age(20).grade(88).build(); —— 全程不打断、类型安全、IDE 可提示子类方法:
// 父类
class Person<B extends Person.Builder<B>> {
protected String name;
protected int age;
public static abstract class Builder<B extends Builder<B>> {
protected String name;
protected int age;
protected abstract B self();
public B name(String name) { this.name = name; return self(); }
public B age(int age) { this.age = age; return self(); }
public abstract Person<B> build();
}
}
// 子类
class Student extends Person<Student.Builder> {
private int grade;
public static class Builder extends Person.Builder<Builder> {
private int grade;
@Override protected Builder self() { return this; }
public Builder grade(int grade) { this.grade = grade; return self(); }
@Override public Student build() {
Student s = new Student();
s.name = this.name;
s.age = this.age;
s.grade = this.grade;
return s;
}
}
}


















