如何使用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()代码>