2010-11-12 85 views
16

在Java中,當從一個對象轉換爲其他類型時,爲什麼第二行產生與該轉換相關的警告,但第一行不是?Java:將對象轉換爲通用類型

void a(Object o) { 
    Integer i = (Integer) o; 
    List<Integer> list = (List<Integer>) o; 
} 

/*Type safety: Unchecked cast from Object to List<Integer>*/ 
+0

第二行產生警告,因爲只有泛型纔會生成這樣的警告。第一個不包含泛型,因此沒有警告。 – 2014-07-15 12:17:39

回答

24

這是因爲對象不會真正來,作爲一個List<Integer>在執行時由於類型擦除檢查。它真的只是將它投射到List。例如:

List<String> strings = new ArrayList<String>(); 
strings.add("x"); 
Object o = strings; 

// Warning, but will succeeed at execution time 
List<Integer> integers = (List<Integer>) o; 
Integer i = integers.get(0); // Bang! 

更多信息,請參見Angelika Langer's Java Generics FAQ,特別是type erasure section

5

Jon的答案是正確的,但偶爾你無法避開那個警告(就像你在使用舊版API時一樣)。在這種情況下,你可以取消此警告,像這樣:

@SuppressWarnings("unchecked") 
List<Integer> list = (List<Integer>) someApiThatReturnsNonGenericList(); 
6

爲了清楚起見,讓我稍微改寫例子...

我會說,在cruxial差異之間:

void a(Object o) { 
    Integer i = (Integer) o; 
    ... 
} 

void a(Object o) { 
    List<Integer> list = (List<Integer>) o; 
    ... 
} 

的是,考慮到有一個類型錯誤,第一次會拋出,立即拋出一個RuntimeException(具體來說,是一個ClassCastException)執行時。

,而第二個可能沒有 - 只要輸入參數o是任何種類的List<?>,執行將只進行,不正確的投儘管

代碼是否會在某處以後是否拋出異常取決於您對列表所做的操作。

但無論如何,異常可能不會被投擲在製作的線路上,但在別的地方(這可能是一個難以追查的錯誤)或根本不會。

這就是我所理解的,是編譯器設計者在第二種情況下認爲適當的警告的原因。

+1

優秀的解釋。 – Trilarion 2013-06-04 20:51:17

+0

第一個*不會總是拋出CastClassException。傳入的對象很可能是一個'Integer'。第一行MIGHT會拋出一個異常,就像第二行可能會出現「o」不是List的情況。 – 2014-07-15 12:16:09

+0

@熱舔:是的,這就是爲什麼我寫了「因爲有一個類型錯誤」,上面 - 我甚至放大膽;) – Rop 2014-07-23 08:42:33

相關問題