2013-11-23 92 views
0

在Java Integer延伸NumberJava泛型奇怪的行爲

然後下面的代碼是編譯:

List<Number> list1 = null; 
List<? super Integer> list2 = null; 
list2 = list1; 

儘管此代碼是未編譯:

List<? super Number> list1 = null; 
List<? extends Integer> list2= null; 
list1 = list2; 

的問題是爲什麼?

+2

您是否注意到您的作業在兩個代碼中均被顛倒過來。將第一個代碼更改爲 - 「list1 = list2」,並且它也不會編譯。 –

回答

5

讓我們看看會去錯的,如果它會編譯:

// Suppose list1, and list2 are initialized like this 
List<? super Number> list1 = new ArrayList<Object>(); // valid assignment 
List<? extends Integer> list2 = new ArrayList<Integer>(); // valid 

// had this been valid, list1 and list2 both point to ArrayList<Integer> 
list1 = list2; 

// This is fine, as list1 declared type is `List<? super Number>` 
list1.add(new Float(2.4f)); 

// The below code will compile fine, as list2.get(0) type is Integer. 
// But it would throw ClassCastException at runtime. 
Integer in = list2.get(0); 

所以,爲了避免它運行時,編譯器給你一個編譯時錯誤。

但是,對於第一種情況,您已以某種方式反轉了分配,因此2個代碼之間的比較沒有意義。將第一個代碼更改爲:

List<Number> list1 = null; 
List<? super Integer> list2 = null; 
list1 = list2; 

它也會失敗。

另外,在第二個代碼中反轉賦值也會導致代碼無法編譯。

一些解釋:

那你必須記住的是,超類引用指向子類對象,而不是相反。如果可以從list1捕獲轉換的所有列表也可以從已聲明的類型list2捕獲轉換,那麼轉讓list2 = list1將是有效的,否則它將無法編譯。

對於第一代碼:

  • List<? super Integer>可以捕獲轉換爲以下列表:
    • List<Integer>
    • List<Number>
    • List<Object>
    • List<Serializable>

由於List<Number>有沒有在列表中,那麼分配list2 = list1是有效的,因爲list1只能指向一個List<Number>。但是,反向分配list1 = list2無效,因爲List<Integer>不是List<Number>的子類型。

類似地,對於第二代碼:

  • List<? super Number>可以捕獲轉換爲:

    • List<Object>
    • List<Serializable>
    • List<Number>
  • List<? extends Integer>可以捕獲轉換爲:

    • List<Integer>

由於List<Integer>未捕獲兌換從List<? super Number>,所以list1 = list2是無效的。

此外,由於List<Object>和其他所有列表都不能從List<? extends Integer>捕獲轉換,所以list2 = list1也是無效的。

+0

是的,但問題是爲什麼一個工作,另一個不是 – Bohemian

+0

@Bohemian剛纔看到他的第一個代碼有不同的方向分配。所以,這將編譯。將其更改爲'list1 = list2'將會失敗。 –

+0

足夠好的+1! – Bohemian

0

(1)在第一個示例中,List<Number>List<? super Integer>「捕獲」。 A List<Number>List<? super Integer>

(2)但在第二個示例中,List<? extends Integer>而不是List<? super Number>捕獲。

例如,您可以添加Number s到List<? super Number>,但你不能非IntegerNumber s到List<? extends Integer>補充。

List<? super Number> list1 = new ArrayList<Number>(); 
list1.add(0.5);  //okay 
List<? extends Integer> list2 = new ArrayList<Integer>(); 
list2.add(0.5); //not okay 

因此,你不能分配list1list2,因爲list2不支持一切的list1類型應該。

+0

我不是要將數字添加到List <?擴展Integer>。我正在嘗試將Integer添加到List <?超級號碼>,但它不起作用 –

+0

但@Babibu,如果您要將'list1'設置爲'list2',則'list1'的類型必須支持'list2'的所有操作。 –

+0

沒有人添加任何東西,有一個嘗試的任務。 –