Java多个泛型集合参数编译错误

时间:2010-05-24 03:30:01

标签: java generics collections compiler-errors

太奇怪了!请先查看代码:

public class A {}

public class B extends A {}

public class C extends A {}

public class TestMain {

    public <T extends A> void test(T a, T b) {}

    public <T extends A> void test(List<T> a, List<T> b) {}

    public void test1(List<? extends A> a, List<? extends A> b) {}

    public static void main(String[] args) {
        new TestMain().test(new B(), new C());
        new TestMain().test(new ArrayList<C>(), new ArrayList<C>());
        new TestMain().test(new ArrayList<B>(), new ArrayList<C>());
        new TestMain().test1(new ArrayList<B>(), new ArrayList<C>());
    }
}

语句new TestMain().test(new ArrayList<B>(), new ArrayList<C>())收到编译错误:

  

绑定不匹配:TestMain类型的通用方法测试(T,T)不适用    对于参数(ArrayList<B>, ArrayList<C>)。推断类型    ArrayList<? extends A>不是有界参数的有效替代    <T extends A>

然而:

 new TestMain().test(new B(), new C())  --> compiled ok

 new TestMain().test(new ArrayList<C>(), new ArrayList<C>()) --> compiled ok

 new TestMain().test1(new ArrayList<B>(), new ArrayList<C>()) --> compiled ok

如果我们在方法名称之前定义泛型,则第二个通用List参数的类型似乎必须与第一个通用{{1}}参数的类型相同。但是如果我们在参数中定义泛型则没有限制。

它是编译程序的功能还是错误?有没有关于它的文件?

2 个答案:

答案 0 :(得分:18)

绝对没有错误;你只是误解了泛型中的子类型规则。

因为我们有B extends A

  • BA
  • 的子类型
  • instanceof B也是instanceof A

由于Java数组是协变的:

  • B[]A[]
  • 的子类型
  • instanceof B[]也是instanceof A[]

然而,Java泛型是不变的:

  • List<B>不是List<A>
  • 的子类型
  • instanceof List<B>不是instanceof List<A>

如果您有以下通用方法声明:

public <T extends A> void test(List<T> a, List<T> b) 

然后,正如此处明确说明的那样,对于类型参数a的某些捕获转换,bList<T>必须具有相同的类型<T extends A>

由于List<B>List<C>是两种不同的类型,因此您不能将它们作为test的实际参数混合使用。此外,即使BCA的子类型,泛型也是不变的,因此List<B>List<C>都不是List<A>。< / p>

因此,

test(new ArrayList<B>(), new ArrayList<C>()); // error!!! doesn't compile!!!

不编译,这是预期的行为。

另见

相关问题

关于泛型类型规则:

使用superextends

关于实际的通用错误:

答案 1 :(得分:9)

这不是一个错误,只是仿制药很复杂。尝试将第二种测试方法更改为:

    public <T extends A, K extends A> void test(List<T> a, List<K> b) {

基本上在你所拥有的东西中没有类型T可以满足你传入的东西,不像第一种方法,其中B和C只是被视为A.这种行为的实际名称逃脱了我但是应该在文献中有很多例子。

简而言之,即使B是A的孩子,List&lt; B&gt;不是List&lt; A&gt;的孩子。