2011-05-18 62 views
7

有人請向我解釋爲什麼在下面的代碼示例中標記爲//this line gives a compile error (why?)的行不起作用?爲什麼將一個ArrayList的泛型轉換爲超類不起作用?

import java.util.ArrayList; 

public class GenericCastCheck { 

    class A{ 
    } 

    class B extends A{ 
    } 

    public static void main(String[] args) { 

     A aObject = new A(); 
     B bObject = new B(); 

     //this line works fine 
     aObject = bObject; 
     //this line gives a compile (expected) 
     bObject = aObject; 

     ArrayList<A> aList = new ArrayList<A>(); 
     ArrayList<B> bList = new ArrayList<B>(); 

     //this line gives a compile error (why?) 
     aList = bList; 
     //this line gives a compile error (expected) 
     bList = aList; 
    } 
} 

具體而言,當我們說bListArrayList<B>型的,它並不意味着它的每一個元素是B一個實例?如果是這樣,那麼如果我們可以將B的單個實例投射到A,那麼將它投射到ArrayList<A>會出現什麼問題?

謝謝。

回答

10

問題是這樣的:

ArrayList<A> aList = new ArrayList<A>(); 
ArrayList<B> bList = new ArrayList<B>(); 
aList = bList; // if this were valid... 
aList.add(new A()); // ...what should happen here? 
B b = bList.get(0); // ...and here? 

如果你做陣列同樣的事情,在運行時獲得第4行的ArrayStoreException信息。對於泛型集合,決定在編譯時防止這種事情。

+0

非常感謝。我意識到我應該使用'aList = new ArrayList (bList);'而不是'aList = bList',它也編譯得很好。 :) – Animesh 2011-05-18 13:32:23

5

因爲泛型是嚴格的。它們不covarient

ArrayList<A> ALIST只能引用一個ArrayListA


類型的從wiki

不同於陣列,通用類是 既不協變也不逆變。 例如,既不List<String>也不 List<Object>是其他的 的子類型:

// a is a single-element List of String 
List<String> a = new ArrayList<String>(); 
a.add("foo"); 

// b is a List of Object 
List<Object> b = a; // This is a compile-time error 

然而,一般類型參數可以 包含通配符(對於僅使用 一旦是 額外類型參數的快捷方式)。例如:鑑於其上解釋進行操作的方法的要求 ,任何物體的 ,然後可以在 對象來執行的唯一 操作是那些爲其 類型關係可以保證 是安全的。

// a is a single-element List of String 
List<String> a = new ArrayList<String>(); 
a.add("foo"); 

// b is a List of anything 
List<?> b = a; 

// retrieve the first element 
Object c = b.get(0); 
// This is legal, because we can guarantee 
// that the return type "?" is a subtype of Object 

// Add an Integer to b. 
b.add(new Integer (1)); 
// This is a compile-time error; 
// we cannot guarantee that Integer is 
// a subtype of the parameter type "?" 

通配符也可以被綁定,例如, 「? extends Foo」或「? super Foo」分別爲 上限和下限。 這允許改進許可的 表現。示例:給定一個List<? extends Foo>,那麼可以檢索一個元素 並將其安全地分配給類型(協方差)的Foo 。給定一個List<? super Foo>,那麼Foo對象可以安全地添加爲 (反變量) 。

0

的Animesh,

即使類B是A的子類型,ArrayList的< B>不是ArrayList的< A的一個子類型>。它與B []中的同一行不是A []的子類型。這是兩個獨立的無關類型。

+2

其實,B [] *是*如果A [] ...是子類型... – 2011-05-18 12:16:28

0

因爲有C<A>C<B>之間在Java中沒有亞型關係,即使是AB或反之亦然的超類型。

如果您對維基百科中的詳細查找co-/contra-variance感興趣,

注意,在Java數組是共變體,這意味着A[]B[]的超類型如果AB的超類型。這就是爲什麼你有時會用數組獲得奇怪的轉換異常的原因。

相關問題