[英]Adding a string to a list throws Integer NFE on double * parsed int
[英]Adding String to List<Integer>
以下代碼的結果:
public class ListIntegerDemo1 {
public static void addToList(List list) {list.add("0067");list.add("bb");}
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
addToList(list);
System.out.println(list.get(0));
}
}
是"0067"
。
我希望將RuntimeException或類似的東西添加到Integer List中。
為什么沒有任何問題?
在運行時,通用類型參數被刪除,因此List<Integer>
成為List
,您可以向其添加任何引用類型。
如果將addToList(List list)
更改為addToList(List<Integer> list)
,則編譯器將阻止您在此方法中將String添加到該列表。
為什么不引發異常有兩個原因,這取決於我們如何看待這個特定示例。 還取決於我們認為應該拋出異常的原因或位置 。 (如果我們認為應該拋出一個,因為顯然Java則認為是其他情況。)
即使我們知道為什么add
不會引發異常,問題中的代碼還是很棘手的,因為一個原因與Java選擇重載的方式有關。 我建議運行以下程序以更好地理解:
class Example {
static void m(int arg) {
System.out.println("int " + arg);
}
static void m(Object arg) {
System.out.println("Object " + arg);
}
public static void main(String[] args) {
m(new Integer(0));
}
}
打印Object 0
。 為什么? 因為Java在三個階段搜索過載:*
這些階段是“短路”,因此在m(new Integer(0))
的情況下,階段1在考慮需要進行裝箱操作的int
重載之前找到Object
重載。 由於發現了過載,因此不嘗試第二階段。
對於ListIntegerDemo1
發生相同的情況,其中選擇了System.out.println(Object)
。
泛型被刪除 ,這意味着:
list.get
實際上返回Object
。 Integer
,編譯器會像(Integer) list.get(0)
一樣插入(Integer) list.get(0)
。 但是不需要插入強制類型轉換來調用Object
重載,因此不會引發異常。
使用原始類型 List
將String
添加到List<Integer>
過程稱為堆污染 。 問題中的代碼是為什么堆污染如此嚴重的一個示例:因為有時我們沒有發現它。 有時我們會在更晚的時間找到它,而不知道錯誤實際上是在哪里引起的。
如果執行此操作,將引發異常:
Integer i = list.get(0);
System.out.println(i);
因為在這種情況下,需要強制轉換來執行分配。
還有,如果我們這樣做:
public class ListIntegerDemo1 {
public static void addToList(List list) {list.add(67);list.add(0xbb);}
public static void main(String[] args) {
List<String> list = new ArrayList<>();
addToList(list);
System.out.println(list.get(0));
}
}
因為在這種情況下,選擇System.out.println(String)
更為具體,並插入了強制類型轉換。
通過使用Collections#checkedList
我們還可以防止List<Integer>
被不安全的代碼污染:
List<Integer> list = Collections.checkedList(
new ArrayList<>(), Integer.class);
在這種情況下, add
在addToList
內部的addToList
調用中引發異常。
當然,最好的解決方案是不使用原始類型:
static void addToList(List<String> list) {
list.add("0067");
list.add("bb");
}
現在,我們無法將List<Integer>
傳遞給該方法。
addToList
也可以接受List<? super String>
List<? super String>
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.