2

假设我有以下接口和实现类:

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>>

笏?getFoo() 的返回类型实际上与 printFoo() 的参数类型相同!

这些错误还是我错过了什么?

4

3 回答 3

3

问题是,这FooType可能不仅仅是Bar. 您可以返回FooType.

class NotBar implements Foo<NotBar> {例如,如果你有

 obj.<NotBar>getFoo();

现在真正的论点FooTypeNotBar

于 2012-11-29T19:45:01.383 回答
0

知道了!感谢 Meriton 回答了这个版本的问题:

如何用编译时泛型验证替换运行时 instanceof 检查

我需要通过执行以下操作来逐步通过printFoo(getFoo())-part 编译器:

public <FooType extends Foo<FooType>> void doPrint() {
    FooType foo = getFoo();
    printFoo(foo);
}

然后打电话doPrint()

然后一切正常。

所以,我猜即使“为什么?” 中间可能是我缺乏理解(感谢 Bhesh 清理了那部分),“WAT?” 最后是合理的,因为这确实应该可以工作...例如,由于某种原因,在上面的代码中内联“foo”的变量定义是不行的...

于 2012-11-30T00:45:46.117 回答
0

问题是,使用您声明的方法:

public <FooType extends Foo<FooType>> FooType doGetFoo() 

这是一个泛型方法,表明我应该取回我指定的泛型类型。例如,如果我有一个Bat扩展的调用,Foo<Bat>我调用instance.<Bat>doGetFoo()它应该返回一个实例,Bat而不是硬编码返回一个实例,Bar其中不一定是泛型中指定的类的实例。如果您删除下面的泛型,您应该没问题:

public Foo<?> doGetFoo(){
    return new Bar();
}
于 2012-11-29T19:50:02.323 回答