簡體   English   中英

將字符串添加到列表<Integer>

[英]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在三個階段搜索過載:*

  1. 第一階段尋找過載,不允許裝箱,拆箱和可變參數。
  2. 第二階段尋找允許裝箱和拆箱的過載。
  3. 第三階段尋找允許裝箱,拆箱和可變參數的重載。

這些階段是“短路”,因此在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重載,因此不會引發異常。

使用原始類型 ListString添加到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);

在這種情況下, addaddToList內部的addToList調用中引發異常。

當然,最好的解決方案是不使用原始類型:

static void addToList(List<String> list) {
    list.add("0067");
    list.add("bb");
}

現在,我們無法將List<Integer>傳遞給該方法。

addToList也可以接受List<? super String> List<? super String>


*在15.12.2中有詳細說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM