2014-03-19 140 views
1

我有一個List<List<Integer>>類型的變量e4,我想用new ArrayList<ArrayList<Integer>>()進行初始化。我希望這會起作用,類似於如何將它分配給List<Integer>-類型的變量a new ArrayList<Integer>()。相反,有一個編譯錯誤;這背後的推理是什麼,是否有必要使用諸如e3e5之類的陳述?在另一個通用接口內使用通用接口

import java.util.List; 
import java.util.ArrayList; 

public class Example { 
    public static void main(String[] args) { 
     // e1-3 compile as expected 
     ArrayList<Integer> e1 = new ArrayList<Integer>(); 
     List<Integer> e2 = new ArrayList<Integer>(); 
     ArrayList<ArrayList<Integer>> e3 = new ArrayList<ArrayList<Integer>>(); 
     // e4 does not compile 
     List<List<Integer>> e4 = new ArrayList<ArrayList<Integer>>(); 
     // e5 does compile 
     List<ArrayList<Integer>> e5 = new ArrayList<ArrayList<Integer>>(); 
    } 
} 

在試圖編譯上面,我得到錯誤信息:

/home/james/Example.java:12: error: incompatible types 
     List<List<Integer>>   e4 = new ArrayList<ArrayList<Integer>>(); 
             ^
required: List<List<Integer>> 
found: ArrayList<ArrayList<Integer>> 
1 error 
+0

類型參數是不同的。 –

+0

http://stackoverflow.com/questions/18666710/why-are-arrays-covariant-but-generics-are-invariant的可能重複 –

回答

4

的原因是,一個List<ArrayList<Integer>>不是List<List<Integer>>,即使一個ArrayList<Integer>List<Integer>。這裏的推理與List<Dog>不是List<Animal>這一事實相同,即使DogAnimal。比喻是ArrayList<Integer>List<Integer>,因爲DogAnimal

以下是備選方案:

1)你的 「E5」,這完全匹配的泛型類型。

List<ArrayList<Integer>>  e5 = new ArrayList<ArrayList<Integer>>(); 

List<List<Integer>> e5 = new ArrayList<List<Integer>>(); 

2)使用通配符:

​​
0

方式的java作品

List<List<Integer>> list = new ArrayList<ArrayList<Integer>> 

將無法​​工作,因爲內部的ArrayList不匹配與列表的類型。它正在尋找一個清單。

你想下面

List<? extends List<Integer>> list = new ArrayList<ArrayList<Integer>>(); 
0

的原因是,在Java泛型是不變的。讓我們先來看看一個很簡單的例子:

// This doesn't compile 
List<Number> list = new ArrayList<Integer>(); 

上述分配不能編譯,因爲一個ArrayList<Integer>不是List<Number>一個亞型,即使IntegerNumber亞型。

使用這一概念,以嵌套的泛型:

// This also shouldn't compile 
List<List<Integer>> list = new ArrayList<ArrayList<Integer>>(); 

雖然ArrayList<Integer>List<Integer>一個亞型,不會使ArrayList<ArrayList<Integer>>List<List<Integer>>亞型。所以它不會編譯。

爲了讓編譯,你可以使用有界通配符:

// This would work now. 
List<? extends List<Integer>> list = new ArrayList<ArrayList<Integer>>(); 
0
Whenever you are specifying ; 

List<List<Integer>> e4 = new ArrayList<ArrayList<Intger>>(); 

This stands out to be wrong because when you are creating the ArrayList (Implementation of the List) e4 you are specifying that it can contain List (all kinds of implementation of lists) of Integer but while instantiating it you are strictly specifying it as ArrayList of Integer which is contradicting with your declaration. 

Moreover Polymorphism only applies to the base type (Base type means the collection class itself.) 

Your example can be correlated with another example : 

List<Number> l1= new ArrayList<Integer>(); /*This will never compile though Integer is a subclass of Number as we are not only changing the base type but also the generic type which is wrong.*/ 

But this will definitely compile 

List<Number> l2 =new ArrayList<Number>(); //Changed only the base type. 


For better understanding read Sun Certified Programmer for Java 6 by Kathy Sierra and Bert Bates.