12

对于以下代码示例:

public static class Abc<X> { }
public static class Def<Y> { }
public static class Ghi<Z> { }

public void doThis() {
    List<?> listOne;
    List<Abc<?>> listTwo;
    List<Abc<Def<?>>> listThree;
    List<Abc<Def<Ghi<?>>>> listFour;
    List<Abc<Def<Ghi<String>>>> listFive;

    Abc<Def<Ghi<String>>> abcdef;

    abcdef = new Abc<Def<Ghi<String>>>();

    listOne.add(abcdef);    // line 1
    listTwo.add(abcdef);    // line 2
    listThree.add(abcdef);  // line 3
    listFour.add(abcdef);   // line 4
    listFive.add(abcdef);   // line 5
}

第 1、3 和 4 行不编译:

(第 1 行)

The method add(capture#1-of ?) in the type List<capture#1-of ?> is not applicable for the arguments (Abc<Def<Ghi<String>>>)

(第 3 行)

The method add(Abc<Def<?>>) in the type List<Abc<Def<?>>> is not applicable for the arguments (Abc<Def<Ghi<String>>>)

(第 4 行)

The method add(Abc<Def<Ghi<?>>>) in the type List<Abc<Def<Ghi<?>>>> is not applicable for the arguments (Abc<Def<Ghi<String>>>)

但是,第 2 行和第 5 行可以编译。

谁能解释为什么第 1、3 和 4 行不是合法分配?如果通配符参数不能在这些行上以这种方式使用,那么为什么第 2 行的赋值是合法的?

4

1 回答 1

12

listOne.add(abcdef)(第 1 行)是无效的,因为它List<?>代表了一些未知的特定类型的列表。例如,它可能是 a List<String>,所以我们不想添加任何不是 a 的东西String。发生编译器错误是因为Abc<Def<Ghi<String>>>不可分配给?.

listTwo.add(abcdef)(第 2 行)是有效的,因为它List<Abc<?>>表示任何类型Abc的s 的列表。没错——嵌套通配符与顶级通配符不同,它们代表任何类型而不是某些特定类型(换句话说,嵌套通配符不捕获)。编译器允许它,因为它可以分配给. 有关嵌套通配符的进一步讨论,请参阅这篇文章:泛型方法上的多个通配符使 Java 编译器(和我!)非常困惑Abc<Def<Ghi<String>>>Abc<?>

listThree.add(abcdef)(第 3 行)是无效的,因为它List<Abc<Def<?>>>表示任何类型的 s 的Abc列表。Def泛型不是协变的,因此Abc<Def<Ghi<String>>>不能分配给Abc<Def<?>>,即使Def<Ghi<String>>可以分配给Def<?>。出于同样的原因,AList<Integer>不能分配给 a 。List<Number>请参阅这篇文章以获得进一步的解释:List<Dog> 是 List<Animal> 的子类吗?为什么 Java 的泛型不是隐式多态的?

listFour.add(abcdef)(第 4 行)出于同样的原因无效 -Abc<Def<Ghi<String>>>不可分配给Abc<Def<Ghi<?>>>.

listFive.add(abcdef)(第 5 行)是有效的,因为泛型类型完全匹配 -Abc<Def<Ghi<String>>>显然可以分配给Abc<Def<Ghi<String>>>.

于 2014-06-19T16:10:45.527 回答