假设我有以下界面并实现类:
interface Foo<FooType extends Foo<FooType>> {
FooType copy();
}
class Bar implements Foo<Bar> {
public Bar copy() {
return new Bar();
}
}
如果我尝试这样做:
public <FooType extends Foo<FooType>> FooType getFoo() {
return new Bar();
}
我收到编译错误“类型不匹配:无法从Bar转换为FooType”。的为什么吗
我可以通过重写这样的函数来“修复”这个:
@SuppressWarnings("unchecked")
public <FooType extends Foo<FooType>> FooType getFoo() {
return (FooType) new Bar();
}
但是,假设我有这样的功能:
public <FooType extends Foo<FooType>> void printFoo(FooType foo) {
System.out.println(foo.toString());
}
如果我尝试这样做:
printFoo(getFoo());
我收到以下编译错误:
Bound mismatch: The generic method printFoo(FooType) is not applicable
for the arguments (Foo<Foo<FooType>>). The inferred type Foo<Foo<FooType>>
is not a valid substitute for the bounded parameter <FooType extends Foo<FooType>>
WAT? getFoo()的返回类型与printFoo()的参数类型完全相同!
这些错误还是我错过了什么?
答案 0 :(得分:3)
问题在于FooType
可能不仅仅是Bar
。您可以返回FooType
。
e.g。如果你有class NotBar implements Foo<NotBar> {
那么
obj.<NotBar>getFoo();
现在FooType
的实际参数为NotBar
。
答案 1 :(得分:0)
问题在于,使用您声明的方法:
public <FooType extends Foo<FooType>> FooType doGetFoo()
这是一种通用方法,声明我应该返回我指定的泛型的类型。例如,如果我有一个扩展Bat
的呼叫Foo<Bat>
并且我呼叫instance.<Bat>doGetFoo()
它应该返回Bat
的实例,而不是硬编码返回一个实例Bar
with不一定是泛型中指定的类的实例。如果你删除通用如下,你应该没问题:
public Foo<?> doGetFoo(){
return new Bar();
}
答案 2 :(得分:0)
知道了!感谢meriton回答了这个问题的版本:
How to replace run-time instanceof check with compile-time generics validation
我需要通过printFoo(getFoo())
- 部分编译器来执行此操作:
public <FooType extends Foo<FooType>> void doPrint() {
FooType foo = getFoo();
printFoo(foo);
}
然后调用doPrint()
。
然后一切正常。
所以,我猜即使“为什么?”在中间可能是我缺乏理解(感谢Bhesh清理那部分),“WAT?”最后是合理的,因为这真的应该有效...例如,由于某种原因,在上面的代码中内联“foo”的变量定义是不行的......