如何使用Java泛型两次扩展生成器类?

如何使用Java泛型两次扩展生成器类?,java,generics,inheritance,nested-generics,Java,Generics,Inheritance,Nested Generics,我有一个要扩展的生成器类,下面是简单的版本: class A { public A withSomeAStuff() { return this; } } A a = new A().withSomeAStuff(); 当我扩展它时,我知道我可以毫无问题地做到这一点: class AA<T extends AA> { public T withSomeAStuff() { return (T) this; } } cl

我有一个要扩展的生成器类,下面是简单的版本:

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();
AA级{
与someastuff()的公共关系{
返回(T)这个;
}
}
BB类扩展为AA类{
公共BB和SomeBStuff(){
归还这个;
}
}
AA=新的AA()。使用someastuff();
BB BB=新BB().带someastuff().带somebstuff();
但现在我想用另一个类进一步扩展它,所以我尝试以下方法:

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();
AAA级{
与someastuff()的公共关系{
返回(T)这个;
}
}
BBB级扩展AAA级{
使用somebstuff()进行公共测试{
返回(T)这个;
}
}
类别CCC扩展BBB{
带有SomeCstuff()的公共CCC{
归还这个;
}
}
AAA=新的AAA()。使用someastuff();
BBB BBB=新的BBB().withSomeAStuff().withSomeBStuff()//在这里休息!
CCC=新的CCC().带someastuff().带somebstuff().带somecstuff();
我的新CCC课程很好,但我的BBB课程坏了,我不知道为什么


我需要做什么来修复它呢?

在类型声明中引入泛型时,在创建该类型的对象时也使用泛型

    AAA<AAA> aaa = new AAA<>().withSomeAStuff();
    BBB<BBB> bbb = new BBB<>().withSomeAStuff().withSomeBStuff(); //Does not break anymore.
    CCC ccc = new CCC().withSomeAStuff().withSomeBStuff().withSomeCStuff();
AAA=new AAA().withSomeAStuff();
BBB BBB=新的BBB().withSomeAStuff().withSomeBStuff()//不再破碎。
CCC=新的CCC().带someastuff().带somebstuff().带somecstuff();
注意: 虽然这将解决编译器错误,但这并不是一种万无一失的方法,而且保证在任何情况下都能工作。您将收到编译器警告以确认这一点

比如你可以

BBB<CCC> bbb = new BBB<CCC>().withSomeAStuff().withSomeBStuff();
BBB BBB=new BBB().withSomeAStuff().withSomeBStuff();

并在运行时受到震动。

切勿忽略原始类型警告:

我添加了一个方法
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();
}
AAA级{
与someastuff()的公共关系{
返回自我();
}
@抑制警告(“未选中”)
受保护的T self(){
返回(T)这个;
}
}
BBB级扩展AAA级{
使用somebstuff()进行公共测试{
返回自我();
}
}
类别CCC扩展BBB{
带有SomeCstuff()的公共CCC{
归还这个;
}
}
公共静态void main(字符串[]args){
AAA=新的AAA()。使用someastuff();
BBB BBB=新的BBB().withSomeAStuff().withSomeBStuff();
CCC=新的CCC().带someastuff().带somebstuff().带somecstuff();
}

这只是问题的一部分。
AAA类
的定义被打破,因为
扩展AAA
是原始的;这会删除类的方法(及其子类)上的泛型。@AndyTurner,True。编辑以迭代漏洞。虽然这停止了最初的问题,但我仍然可以通过以下方法轻松解决:
BBB BBB=new BBB().withSomeAStuff().withSomeAStuff().withSomeBStuff()//此处仍然中断
@Codebender问题在于类定义,而不是它们的实例化方式。请注意,当您编译代码时(直到第二个块;暂时忽略第三个块),编译器将警告您“未检查或不安全的操作”。这应该是你第一次暗示“没有任何问题”不是真的。答案的关键部分是BBB需要定义为
BBB
,并且应该构造为
newBBB()
。那一切都好了,谢谢!但这仍然是不安全的;你只是忽略了警告。@newacct你能给我一个例子,这个cast实际上产生了一个受污染的堆吗?(不使用另一个不安全的强制转换或原始类型)@k5:
class Foo扩展AAA{}class Bar扩展AAA{}Foo x=new Bar()