首頁 >Java >java教程 >為什麼 Java 中泛型方法上的多個通配符會導致混亂?

為什麼 Java 中泛型方法上的多個通配符會導致混亂?

Patricia Arquette
Patricia Arquette原創
2024-11-23 04:03:18725瀏覽

Why Does Multiple Wildcards on Generic Methods in Java Lead to Confusion?

泛型方法上的多個通配符:Java 編譯器難題

簡介

Java 泛型中、通配符(*)代表未知型別。當在泛型方法上使用多個通配符時,可能會導致混亂和意外行為。本文探討了多個通配符的複雜性及其對 Java 類型安全性的影響。

混亂

考慮以下程式碼:

public class TwoListsOfUnknowns {
    static void doNothing(List<?> list1, List<?> list2) { }

    public static void main(String[] args) {
        List<String> list1 = null;
        List<Integer> list2 = null;
        doNothing(list1, list2); // compiles fine!
    }
}

doNothing 中的兩個通配符看起來不相關,允許您使用List來調用它。和列表。但是,對此方法添加以下內容會出現編譯錯誤:

static void doSomethingIllegal(List<?> list1, List<?> list2) {
    list1.addAll(list2); // DOES NOT COMPILE!!!
}

這表明雖然 list1 和 list2 可以是不同的類型,但它們可能存在某種連接,無法直接使用。

嵌套通配符的混亂

進一步調查發現,混亂不在於多個通配符,而在於嵌套通配符:

public class LOLUnknowns1 {
    static void probablyIllegal(List<List<?>> lol, List<?> list) {
        lol.add(list); // this compiles!! how come???
    }
}

即使list 可能是與lol 元素不同的類型,此程式碼編譯也不會出現錯誤。但是,需要注意的是,這種情況會引發有關類型安全的問題。

真相:捕獲轉換

這種混亂源自於稱為捕獲轉換的概念。它允許某些通配符在泛型方法中使用時捕獲特定類型。這就是為什麼下面的 possibleIllegal 變體可以編譯:

static void probablyIllegalAgain(List<List<? extends Number>> lol, List<? extends Number> list) {
    lol.add(list); // compiles fine!!! how come???
}

這裡,lol 中的通配符可以捕獲擴展 Number 的類型,例如 List;或列表。這意味著 mightIllegalAgain 可以接受都是數字列表的參數。

理解嵌套通配符

關鍵要點是多個通配符本身沒有問題。當嘗試使用嵌套通配符捕獲由於類型差異而不“相容”的類型時,會出現混亂。

對於 LOLUnknowns1,List> 中的巢狀通配符是無法捕獲特定類型,因為捕獲對於 lol 的所有可能元素類型來說並不安全。這就是為什麼 list 可以是任何類型,從而導致潛在的類型安全問題。

結論

泛型方法上的多個通配符可能會令人困惑,但了解捕獲轉換和它的局限性至關重要。嵌套通配符需要仔細考慮以確保類型安全。透過遵守這些原則,您可以了解 Java 泛型的複雜性並編寫健全的程式碼。

以上是為什麼 Java 中泛型方法上的多個通配符會導致混亂?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn