[英]type erasure in implementation of ArrayList in Java
我正在閱讀關於Java Generics的這篇文章,並且在那里提到了ArrayList
的構造函數看起來像這樣:
class ArrayList<V> {
private V[] backingArray;
public ArrayList() {
backingArray = (V[]) new Object[DEFAULT_SIZE];
}
}
我無法理解編譯器的類型擦除和類型檢查是如何解釋的那樣。 我得到的一點是type參數被轉換為Object
類型。
我會想象它(用Object
替換所有V
),但這絕對是錯誤的。
class ArrayList<Object> {
private Object[] backingArray;
public ArrayList() {
backingArray = (Object[]) new Object[DEFAULT_SIZE];
}
}
它究竟是如何轉換為Object
類型但仍保留V
的類型安全性? 當我有ArrayList<String>
和ArrayList<Integer>
,每個都有兩個不同的類? 如果不存在,那么存儲String
和Integer
的類型信息在哪里?
您的類型擦除版本不正確。 類型參數聲明不會被刪除到Object
但只會刪除它的用法。 進一步來說:
ArrayList<V>
,它只是ArrayList
。 ArrayList<Integer>
將替換為ArrayList
。 所以,正確的擦除版本將是:
class ArrayList {
private Object[] backingArray;
public ArrayList() {
backingArray = (Object[]) new Object[DEFAULT_SIZE];
}
}
當我有ArrayList和ArrayList時,每個都有兩個不同的類?
不,情況絕對不是這樣。 編譯器僅生成泛型類型或方法的一個字節代碼表示,並將泛型類型或方法的所有實例映射到唯一表示。
如果沒有存儲String和Integer的類型信息的位置?
當編譯器執行類型擦除時,它會根據一些預定義的規則刪除所有類型信息,偶爾添加所謂的橋接方法 ,並添加所需的所有必要類型轉換。
因此,例如,以下使用ArrayList<Integer>
和ArrayList<String>
:
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(1);
int value = list.get(0);
ArrayList<String> list2 = new ArrayList<String>();
list.add("A");
String value2 = list.get(0);
將轉換為有點像這樣:
ArrayList list = new ArrayList();
list.add(1);
int value = (Integer) list.get(0);
ArrayList list2 = new ArrayList();
list.add("A");
String value2 = (String) list.get(0);
進一步閱讀:
你的第二個例子不正確。 類型擦除並不意味着全局將所有內容都轉換為Object
。 正如你猜測的那樣,這幾乎沒有任何意義。 相反,什么類型的擦除做(字面上)以下(借用Jon Skeet ):
List<String> list = new ArrayList<String>();
list.add("Hi");
String x = list.get(0);
這段代碼被翻譯成:
List list = new ArrayList();
list.add("Hi");
String x = (String) list.get(0);
注意轉換為String
,而不僅僅是一個vanilla Object
。 類型擦除“擦除”泛型的類型並將其中的所有對象強制轉換為T
這是一種添加一些編譯時用戶友好性而不會產生運行時成本的聰明方法。 但是,正如文章所聲稱的那樣,這並非沒有妥協。
請考慮以下示例:
ArrayList<Integer> li = new ArrayList<Integer>();
ArrayList<Float> lf = new ArrayList<Float>();
它可能看起來不直觀(或正確),但li.getClass() == lf.getClass()
將評估為true。
好問題。首先進行類型檢查。如果所有內容都編譯(即,在提供編譯類型安全性之后),則會發生類型擦除。
同樣,很多事情都是類型擦除的一部分,其中包括: -
1)Adding casts
2) creating bridge methods
但是首先進行類型檢查,一切都在以后進行
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.