关于Java泛型的一些问题

时间:2012-11-29 19:37:49

标签: java generics type-mismatch

假设我有以下界面并实现类:

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()的参数类型完全相同!

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

3 个答案:

答案 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”的变量定义是不行的......