Java嵌套自引用泛型
我有一个类,它有一个自引用泛型参数和一个属于同一个超类的参数。静态函数与类具有相同的边界Java嵌套自引用泛型,java,generics,Java,Generics,我有一个类,它有一个自引用泛型参数和一个属于同一个超类的参数。静态函数与类具有相同的边界 public class Bar<T extends Bar<T, C>, C extends Bar<C, ?>> { Bar() { foo((T) null); foo((C) null);//compile error } static <S_T extends Bar<S_T, S_C>
public class Bar<T extends Bar<T, C>, C extends Bar<C, ?>> {
Bar() {
foo((T) null);
foo((C) null);//compile error
}
static <S_T extends Bar<S_T, S_C>, S_C extends Bar<S_C, ?>> void foo(S_T t) {
}
}
公共类栏{
Bar(){
foo((T)null);
foo((C)null);//编译错误
}
静态无效foo(S_T T){
}
}
这会产生以下错误
绑定不匹配:类型为Bar的泛型方法foo(S_T)不匹配
适用于参数(C)。推断的类型C不是有效的
替换有界参数
我不明白为什么不能将C
传递到foo()
,因为C
是Bar
,而通配符是Bar
,因为声明中的第二个参数表示它扩展了Bar
我知道这可能是个坏主意,产生的代码很难理解,但我真的想知道为什么它不能编译。我不是泛型高手,但我认为问题在于你声明foo()的类型为
void foo(S\T)
然后在两个不同的上下文中调用它,foo()
需要不同的静态类型
在第一个上下文中,S\u T
具有类型T
,在第二个上下文中,它具有类型C
。但是T
和C
被声明为Bar
和Bar
,它们是静态不兼容的类型。
我猜编译器在第一次调用中计算出了
foo()
的类型,然后正确地假设该类型在整个调用过程中必须保持不变,但事实并非如此。简单的回答是,Java类型推断实际上非常蹩脚
Java没有对Bar
声明中的通配符?
执行任何智能推断,以推断它在逻辑上受Bar<?,?>
(也不是说该边界中的?
本身是有边界的,依此类推)。一旦你把?
放在自己的位置上,Java就知道这些了。尽管没有什么能阻止你在条的声明中把这个绑定放在通配符上,即使这对Java也没有帮助;Java永远不会假设两个独立的?
引用相同的类型,即使深入分析会暗示它们必须是相同的类型。换句话说,即使使用以下代码,编译错误仍然存在:
public class Bar<T extends Bar<T, C>, C extends Bar<C, ? extends Bar<?, ? extends Bar<?, ?>>>> {
Bar() {
foo((T) null);
foo((C) null);//compile error
}
static <S_T extends Bar<S_T, S_C>, S_C extends Bar<S_C, ? extends Bar<?, ? extends Bar<?, ?>>>> void foo(S_T t) {
}
}
public class Bar>>>void foo(S\u T T){
}
}
切换两个foo()调用的顺序仍然会在C行出现错误。好的,尝试更改类声明中C和T的顺序,即do BarI尝试了您建议的更改,错误更改为T,但我认为这只是因为它所做的只是重命名参数,而没有更改任何含义。我尝试了几种不同的方法对参数进行重新排序,错误仍然停留在带有通配符的参数上。此外,我认为虽然C和T彼此不兼容,但两者都应该与静态函数兼容,因为AFAIK的泛型参数基于每次调用时得到的输入;但从我从你的问题中收集到的信息来看,是类层次结构未能编译,而我的类层次结构编译了函数的参数约束,但失败了。是的,我开始怀疑java无法检测到通配符边界之间的连接。我开始尝试提供一个类:Pie扩展了Bar
,而不是通配符。然后函数将Bar
作为foo
的参数类型有什么问题?关于foo
中的sut
您可以使用的唯一信息是,它是一个条
。另外,这使得foo
(至少在理论上)更加通用。该函数的通用参数是什么?你的意思是仅仅定义S_T和S_C而没有任何边界,因为参数中的Bar与Bar类的边界不匹配,这没有多大帮助。我突然想到,如果你想调用foo((C)null)
,你也不关心foo
中Bar
的第二个参数,这意味着为什么不直接调用静态void foo(S_t){}
?这是可行的,取决于你想做什么,因为你不能调用newbar()
如果您使用通配符而不是S_C。
public class Bar<T extends Bar<T, C>, C extends Bar<C, ? extends Bar<?, ? extends Bar<?, ?>>>> {
Bar() {
foo((T) null);
foo((C) null);//compile error
}
static <S_T extends Bar<S_T, S_C>, S_C extends Bar<S_C, ? extends Bar<?, ? extends Bar<?, ?>>>> void foo(S_T t) {
}
}