2014-10-08 78 views
19

爲什麼println打印「湯姆」,而不是表示鑄造到List<Integer>之後的任何運行時異常,而這是無法鑄造List<String>後打印值1?泛型列表<String>和列表<Integer>不表現爲預期的

import java.util.Arrays; 
import java.util.List; 

public class Main { 
    public static void main(String args[]) { 

     List list = Arrays.asList(1, "tom"); 

     System.out.println(((List<Integer>) list).get(1)); 
     // "tom" 

     System.out.println(((List<String>) list).get(0)); 
     // ClassCastException: Integer cannot be cast to String 
    } 
} 
+5

它*顯示運行時異常。 – Maroun 2014-10-08 06:54:56

+0

每次註釋一種類型的列表以獲得期望的輸出,即,列表 list3 = list1; // System.out.println(list3.get(0)); – Aman 2014-10-08 06:56:46

回答

34

println第一個電話被靜態地分派到PrintStream.println(Object)和第二呼叫被分派到PrintStream.println(String)。因此,對於第二次調用,編譯器會將隱式強制轉換爲String,然後在運行時由ClassCastException失敗。

+3

這就是正確答案+1。 – Maroun 2014-10-08 07:00:23

+2

可否請您詳細說明這一點,bcoz我認爲在第一種情況下,如果它打印PrintStream.println(整數)PrintStream.println(字符串)的第二種情況或這兩個shud有PrintStream.println(對象)。 – Aman 2014-10-08 07:06:21

+7

沒有'PrintStream.println(Integer)'。編譯器總是調度到具有最特定簽名的方法。 'Integer'的最具體類型是'Object','String'的最具體類型是'String'。 – ZhekaKozlov 2014-10-08 07:10:13

0
Integer i = new Integer(101); 
String s = new String(i); // undefined and Invalid 
StringBuffer sb = new StringBuffer(i); // defined and Valid 

String s2 = "tom"; 
Integer i2 = new Integer(s2); //defined and valid 

所以,當你指定一個非泛型列表到一個通用的一個是分配,但是當你打印它會檢查類型安全或定義鑄造構造是否有有效的和定義的構造函數,然後它被其他印刷由於缺少用於強制轉換的未定義構造函數,因此類無法投射,因此顯示了類轉換異常。

如果我錯了,請幫我用正確的邏輯...

+0

這與構造函數無關。 – Radiodef 2014-10-08 15:42:47

0

這種類型的問題可以通過使用泛型來避免,並且是使用泛型的主要動機。

這是您的代碼的實際流量,從第二個println()點:

  1. 您的代碼聲明Object類型的ArrayList;

  2. 它向ArrayList添加了IntegerString

  3. 它將您的列表投到String列表中。您的列表被標記爲僅限於String

Java泛型是編譯時功能只讓你列表可以沒有任何問題StringInteger元素接受。與編譯器不同,對象本身不知道它包含的類型。

  • 它attemps中檢索其應該是一個String並且將它轉換爲String隱式的鑄造列表的第一個元素。

  • 致電println(String x)PrintStream類。

  • 但是這第一個元素其實不是String而是Integer。 您不能將Integer轉換爲String

    閱讀Generics in Java動機部分示例。

    相關問題