簡體   English   中英

為什么 Java 泛型不支持原始類型?

[英]Why don't Java Generics support primitive types?

為什么 Java 中的泛型適用於類而不適用於原始類型?

例如,這工作正常:

List<Integer> foo = new ArrayList<Integer>();

但這是不允許的:

List<int> bar = new ArrayList<int>();

Java 中的泛型完全是編譯時構造 - 編譯器將所有泛型用途轉換為正確類型的強制轉換。 這是為了保持與以前的 JVM 運行時的向后兼容性。

這個:

List<ClassA> list = new ArrayList<ClassA>();
list.add(new ClassA());
ClassA a = list.get(0);

變成(大致):

List list = new ArrayList();
list.add(new ClassA());
ClassA a = (ClassA)list.get(0);

因此,任何用作泛型的東西都必須可以轉換為 Object(在本例中get(0)返回一個Object ),而原始類型則不然。 所以它們不能用於泛型。

在 Java 中,泛型的工作方式與它們相同……至少部分是因為它們是在語言設計1幾年后添加到語言中的。 語言設計者在選擇泛型方面受到限制,因為他們不得不提出一種向后兼容現有語言和 Java 類庫的設計

其他編程語言(例如 C++、C#、Ada)確實允許將原始類型用作泛型的參數類型。 但這樣做的另一面是,此類語言對泛型(或模板類型)的實現通常需要為每個類型參數化生成一個不同的泛型類型副本。


1 - Java 1.0 中未包含泛型的原因是時間壓力。 他們覺得必須盡快發布 Java 語言,以填補 Web 瀏覽器帶來的新市場機會。 James Gosling 曾表示,如果他們有時間,他會希望包括泛型。 如果發生這種情況,Java 語言會是什么樣子是任何人的猜測。

在 Java 中,泛型是通過使用“類型擦除”來實現向后兼容的。 所有泛型類型都在運行時轉換為 Object。 例如,

public class Container<T> {

    private T data;

    public T getData() {
        return data;
    }
}

將在運行時被視為,

public class Container {

    private Object data;

    public Object getData() {
        return data;
    }
}

編譯器負責提供正確的類型轉換以確保類型安全。

Container<Integer> val = new Container<Integer>();
Integer data = val.getData()

會變成

Container val = new Container();
Integer data = (Integer) val.getData()

現在的問題是為什么在運行時選擇“對象”作為類型?

答案是Object是所有對象的超類,可以代表任何用戶定義的對象。

由於所有原語都不是從“ Object ”繼承的,因此我們不能將其用作泛型類型。

僅供參考:瓦爾哈拉計划正試圖解決上述問題。

根據Java 文檔,泛型類型變量只能用引用類型實例化,不能用原始類型實例化。

這應該在Project Valhalla下的 Java 10 中出現。

Brian Goetz關於專業化狀態的論文中

關於基元不支持泛型的原因有一個很好的解釋 並且, 它將如何在 Java 的未來版本中實現

Java 的當前擦除實現為所有引用實例化生成一個類,並且不支持原始實例化。 (這是同構轉換,Java 泛型只能覆蓋引用類型的限制來自同構轉換對 JVM 字節碼集的限制,JVM 對引用類型和原始類型的操作使用不同的字節碼。)然而,Java 中的擦除泛型提供了行為參數(泛型方法)和數據參數(泛型類型的原始和通配符實例化)。

...

選擇了同構翻譯策略,其中泛型類型變量在它們被合並到字節碼中時被擦除到它們的邊界。 這意味着無論一個類是否是泛型的,它仍然會編譯為一個具有相同名稱且成員簽名相同的類。 類型安全在編譯時驗證,運行時不受泛型類型系統的約束。 反過來,這強加了泛型只能在引用類型上工作的限制,因為 Object 是最通用的可用類型,並且它不能擴展到原始類型。

集合被定義為需要從java.lang.Object派生的類型。 基本類型根本不這樣做。

為什么Java中的泛型只能用於類,而不能用於原始類型?

例如,這可以正常工作:

List<Integer> foo = new ArrayList<Integer>();

但這是不允許的:

List<int> bar = new ArrayList<int>();

暫無
暫無

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

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