建造者模式-具有递归类型参数的泛型类型(Effective-Java)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了建造者模式-具有递归类型参数的泛型类型(Effective-Java)相关的知识,希望对你有一定的参考价值。
Effective-Java-Chapter 2:
来看看书中的Pizza代码案例(我写了详细注释):
Pizza:
import java.util.EnumSet;
import java.util.Objects;
import java.util.Set;
public abstract class Pizza
public enum Topping HAM, MUSHROOM, ONION, PEPPER, SAUSAGE
final Set<Topping> toppings;
//这种技术称为协变返回类型,其中一个子类方法声明为返回超类中声明的返回类型的子类型。
//它允许客户使用这些构建器,而不需要强制转换。(因为self()函数返回子类自身)
abstract static class Builder<T extends Builder<T>>
//此处限制了 T 只能是Builder的子类(目的:type safe)
EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class);
public T addTopping(Topping topping)
toppings.add(Objects.requireNonNull(topping));
return self();
abstract Pizza build();
// Subclasses must override this method to return "this"
protected abstract T self();
Pizza(Builder<?> builder)
toppings = builder.toppings.clone(); // See Item 50
MyPizza:
import java.util.Objects;
public class NyPizza extends Pizza
public enum Size SMALL, MEDIUM, LARGE
private final Size size;
//Builder1是作者自己做的小修改,方便看区别
public static class Builder1 extends Pizza.Builder<Builder1>
//因为Builder1 extends Pizza.Builder 则 Pizza.Builder<Builder1>成立.
//Pizza.Builder<Builder1>写成Pizza.Builder<Builder2>编译成功
//因为Builder2是Pizza.Builder子类,不过这样的话,self()函数返回的就是Calzone对象了
//递归泛型作用就是限定泛型T只能是自己的子类,达到type safe的目的
private final Size size;
public Builder1(Size size)
this.size = Objects.requireNonNull(size);
@Override
public NyPizza build()
return new NyPizza(this);
@Override
protected Builder1 self()
return this;
//Self类型是在接口中用描述实现接口的具体类型的特殊类型标识,用来安全地从父类型向子类型转换对象
//一般来说,把父类型的对象转换为子类型的对象,都要用强制类型转换。
//利用递归的类型参数,可以避免强制类型转换
private NyPizza(Builder1 builder)
super(builder);
size = builder.size;
Calzone:(与MyPizza类 类似的)
public class Calzone extends Pizza
private final boolean sauceInside;
public static class Builder2 extends Pizza.Builder<Builder2>
private boolean sauceInside = false; // Default
public Builder2 sauceInside()
sauceInside = true;
return this;
@Override
public Calzone build()
return new Calzone(this);
@Override
protected Builder2 self()
return this;
private Calzone(Builder2 builder)
super(builder);
sauceInside = builder.sauceInside;
来看看这3个类之间的关系图(右键点击Pizza类,点那个显示图,就可以看)
注:Builder1和Builder2是我自己做的一点点修改,方便看区别
书中接下来就提到了“协变返回类型”:
T self() 方法 将所需子类对象返回,无需强制类型转换。其次,
Pizza类中的 Builder<T extends Builder<T>> 限制了 T 只能是Builder的子类
对递归类型参数的泛型类型还是不理解的话,可以看看知乎这篇文章:
Java泛型递归模式的意义? - CNife的回答 - 知乎
感谢支持!
以上是关于建造者模式-具有递归类型参数的泛型类型(Effective-Java)的主要内容,如果未能解决你的问题,请参考以下文章
GetMethod 的 Type[] 以获取具有两个参数和一个类型参数的泛型方法