如何使用 Java 泛型扩展构建器 class 两次?
How do I extend a builder class twice using Java generics?
我有一个要扩展的构建器 class,这里是简单版本:
class A {
public A withSomeAStuff() {
return this;
}
}
A a = new A().withSomeAStuff();
当我扩展它时,我知道我可以毫无问题地做到这一点:
class AA<T extends AA> {
public T withSomeAStuff() {
return (T) this;
}
}
class BB extends AA<BB> {
public BB withSomeBStuff() {
return this;
}
}
AA aa = new AA().withSomeAStuff();
BB bb = new BB().withSomeAStuff().withSomeBStuff();
但现在我想用另一个 class 进一步扩展它,所以我试试这个:
class AAA<T extends AAA> {
public T withSomeAStuff() {
return (T) this;
}
}
class BBB<T extends BBB> extends AAA<T> {
public T withSomeBStuff() {
return (T) this;
}
}
class CCC extends BBB<CCC> {
public CCC withSomeCStuff() {
return this;
}
}
AAA aaa = new AAA().withSomeAStuff();
BBB bbb = new BBB().withSomeAStuff().withSomeBStuff(); //breaks here!
CCC ccc = new CCC().withSomeAStuff().withSomeBStuff().withSomeCStuff();
我的新 CCC class 工作正常,但我的 BBB class 坏了,我不知道为什么。
我需要做什么来修复它?
当您在类型声明中引入泛型时,在创建该类型的对象时也使用它。
AAA<AAA> aaa = new AAA<>().withSomeAStuff();
BBB<BBB> bbb = new BBB<>().withSomeAStuff().withSomeBStuff(); //Does not break anymore.
CCC ccc = new CCC().withSomeAStuff().withSomeBStuff().withSomeCStuff();
注:
虽然这将解决您的编译器错误,但这不是万无一失的方法,并且保证在所有情况下都能正常工作。您将收到编译器警告以确认这一点。
例如你可以这样做,
BBB<CCC> bbb = new BBB<CCC>().withSomeAStuff().withSomeBStuff();
并在运行时受到冲击。
永远不要忽略原始类型警告:What is a raw type and why shouldn't we use it?
我添加了一个方法 self()
因此您的代码中只有一个未经检查的转换。
class AAA<T extends AAA<T>> {
public T withSomeAStuff() {
return self();
}
@SuppressWarnings("unchecked")
protected T self() {
return (T) this;
}
}
class BBB<T extends BBB<T>> extends AAA<T> {
public T withSomeBStuff() {
return self();
}
}
class CCC extends BBB<CCC> {
public CCC withSomeCStuff() {
return this;
}
}
public static void main(String[] args) {
AAA<?> aaa = new AAA<>().withSomeAStuff();
BBB<?> bbb = new BBB<>().withSomeAStuff().withSomeBStuff();
CCC ccc = new CCC().withSomeAStuff().withSomeBStuff().withSomeCStuff();
}
我有一个要扩展的构建器 class,这里是简单版本:
class A {
public A withSomeAStuff() {
return this;
}
}
A a = new A().withSomeAStuff();
当我扩展它时,我知道我可以毫无问题地做到这一点:
class AA<T extends AA> {
public T withSomeAStuff() {
return (T) this;
}
}
class BB extends AA<BB> {
public BB withSomeBStuff() {
return this;
}
}
AA aa = new AA().withSomeAStuff();
BB bb = new BB().withSomeAStuff().withSomeBStuff();
但现在我想用另一个 class 进一步扩展它,所以我试试这个:
class AAA<T extends AAA> {
public T withSomeAStuff() {
return (T) this;
}
}
class BBB<T extends BBB> extends AAA<T> {
public T withSomeBStuff() {
return (T) this;
}
}
class CCC extends BBB<CCC> {
public CCC withSomeCStuff() {
return this;
}
}
AAA aaa = new AAA().withSomeAStuff();
BBB bbb = new BBB().withSomeAStuff().withSomeBStuff(); //breaks here!
CCC ccc = new CCC().withSomeAStuff().withSomeBStuff().withSomeCStuff();
我的新 CCC class 工作正常,但我的 BBB class 坏了,我不知道为什么。
我需要做什么来修复它?
当您在类型声明中引入泛型时,在创建该类型的对象时也使用它。
AAA<AAA> aaa = new AAA<>().withSomeAStuff();
BBB<BBB> bbb = new BBB<>().withSomeAStuff().withSomeBStuff(); //Does not break anymore.
CCC ccc = new CCC().withSomeAStuff().withSomeBStuff().withSomeCStuff();
注: 虽然这将解决您的编译器错误,但这不是万无一失的方法,并且保证在所有情况下都能正常工作。您将收到编译器警告以确认这一点。
例如你可以这样做,
BBB<CCC> bbb = new BBB<CCC>().withSomeAStuff().withSomeBStuff();
并在运行时受到冲击。
永远不要忽略原始类型警告:What is a raw type and why shouldn't we use it?
我添加了一个方法 self()
因此您的代码中只有一个未经检查的转换。
class AAA<T extends AAA<T>> {
public T withSomeAStuff() {
return self();
}
@SuppressWarnings("unchecked")
protected T self() {
return (T) this;
}
}
class BBB<T extends BBB<T>> extends AAA<T> {
public T withSomeBStuff() {
return self();
}
}
class CCC extends BBB<CCC> {
public CCC withSomeCStuff() {
return this;
}
}
public static void main(String[] args) {
AAA<?> aaa = new AAA<>().withSomeAStuff();
BBB<?> bbb = new BBB<>().withSomeAStuff().withSomeBStuff();
CCC ccc = new CCC().withSomeAStuff().withSomeBStuff().withSomeCStuff();
}