我遇到了错误,我认为这是一种直接的推论,其中使用泛型的方法将泛型类的版本指定为一个参数,而对于第二个参数,它指定了用于前一个参数的版本的类型。
static class GenericClass<T0>
{
T0 getT()
{
return null;
}
static <T1> void func3( GenericClass<T1> a, T1 b )
{
}
}
void testcase( GenericClass<? extends Integer> a )
{
GenericClass.func3( a, a.getT() );
}
不幸的是,它显示为错误:
"The method func3(GenericClass<T1>, T1) in the type GenericClass is not applicable for the arguments (GenericClass<capture#6-of ? extends Integer>, capture#7-of ? extends Integer)"
但是,对 func3 header 的此更改有效。
static <T1> void func3( GenericClass<? extends T1> a, T1 b )
测试用例方法的 header 也会发生变化。
void testcase( GenericClass<Integer> a )
即使测试用例 header 没有给出该类的具体类型,该类指定的返回类型将与其泛型类型相同,那么为什么错误消息表明它们可能是两种不同的类型?
最佳答案
这个例子并不明显,因为 Integer
是 final
,让我们举个例子,其中 Parent
有两个子类,Foo
和Bar
。
? extends Parent
表示 Parent
的某些特定子类型。所以GenericClass<Foo>
和GenericClass<Bar>
可以在 GenericClass<? extends Parent>
的地方使用预计。
这里
static <T1> void func3( GenericClass<T1> a, T1 b )
您有一个泛型方法,其中两个参数声明中都使用了泛型类型参数。编译器必须保证方法调用期间提供的两个参数的类型都是正确的。
鉴于此
GenericClass<? extends Parent> a = ...;
GenericClass.func3( a, a.getT() );
它没有办法做到这一点。您必须首先了解 Java 不知道这两个参数来自同一来源。它所关注的只是它们的类型。
第一个参数的类型为 GenericClass<? extends Parent>
而第二个参数的类型为 ? extends Parent
。考虑以下因素
GenericClass<? extends Parent> a = new GenericClass<Foo>(someFoo);
GenericClass<? extends Parent> b = new GenericClass<Bar>(someBar);
GenericClass.func3( a, b.get());
这两个参数与上面的方法调用具有完全相同的编译时类型,但更容易理解为什么它会失败。它不能保证T
两个参数将绑定(bind)到相同的类型。因此它一定会失败。
关于Java泛型类型推导错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25676368/