Java Generics:使用嵌套通配符参数进行赋值

时间:2014-06-19 13:57:21

标签: java generics type-parameter nested-generics

对于以下代码示例:

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行的赋值是合法的?

1 个答案:

答案 0 :(得分:9)

listOne.add(abcdef)(第1行)无效,因为List<?>表示某种未知特定类型的列表。例如,它可能是List<String>,因此我们不想添加任何不是String的内容。发生编译器错误是因为Abc<Def<Ghi<String>>>无法分配给?

listTwo.add(abcdef)(第2行)有效,因为List<Abc<?>>代表任何类型Abc列表。这是正确的 - 嵌套通配符与顶级通配符的不同之处在于它们代表任何类型而不是某些特定类型(换句话说,嵌套通配符不是{{3} })。编译器允许它,因为Abc<Def<Ghi<String>>>可分配给Abc<?>。有关嵌套通配符的进一步讨论,请参阅此帖子:capture

listThree.add(abcdef)(第3行)无效,因为List<Abc<Def<?>>>代表任意类型Abc的{​​{1}}列表。泛型不是协变的,因此Def不能分配给Abc<Def<Ghi<String>>>,即使Abc<Def<?>>可分配给Def<Ghi<String>>。由于同样的原因,Def<?>无法分配给List<Integer>。有关详细说明,请参阅此帖子:Multiple wildcards on a generic methods makes Java compiler (and me!) very confused

由于同样的原因,

List<Number>(第4行)无效 - listFour.add(abcdef)无法转让给Abc<Def<Ghi<String>>>

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