簡體   English   中英

HashMap實現中的泛型

[英]Generics in HashMap implementation

在Java實現中,我發現

 transient Entry[] table; 
 which is initiated in constructor as
 table = new Entry[capacity];

我知道並了解不允許創建通用數組,但是我無法理解的是整個過程是如何工作的。 我的意思是當我們做類似的事情時

HashMap<Integer, String> hMap = new HashMap<Integer, String>();

上面的代碼如何導致創建類型為<Integer, String>的Entry數組

好吧,很少有人無法理解我的要求。 改寫我要問的是做這樣的事情有什么意義

HashMap<Integer, String> hMap = new HashMap<Integer, String>();

當它不導致

Entry<Integer, String>

泛型是編譯時的安全性。 在運行時,地圖僅了解對象。 這稱為類型擦除 為了進一步嚇到您,以下代碼將毫無問題地運行:

Map<Integer, Integer> safeMap = new HashMap<>();
Map unsafeMap = safeMap;
unsafeMap.put("hello", "world");

您將在編譯時收到警告,因為您使用的是原始Map而不是通用Map,但在運行時根本不執行任何檢查,因為該Map是可以存儲任何對象的良好舊Map。 只有編譯器才能阻止您在映射或整數中添加字符串。

該實現使類型為Entry<K,V>對象數組

static class Entry<K,V> implements Map.Entry<K,V>

而不提供通用類型參數( source )。 這是允許的,但要理解編譯器不再保證類型安全。 例如,在代碼的其他地方,您可以編寫

Entry<K,V> e = table[bucketIndex];

編譯器將允許您執行此操作。 如果您確定始終將table[]元素設置為nullEntry<K,V> ,則可以知道分配是正確的。

這樣做沒有問題的原因是Java中的泛型類型是通過類型擦除實現的,即Entry<K,V>對象Entry<Integer,Integer>Entry<String,Long>在運行時沒有區別。

嘗試以這種方式思考Java泛型:類型參數僅適用於引用類型的表達式靜態類型,不適用於在運行時引用值所引用的實際實例類型

在閱讀Java代碼時,我發現了開發正確直覺的上述關鍵。 所以下次你看到

new HashMap<Integer, String>()

讀如下:“這是類型為HashMap<Integer, String>的實例創建表達式。在運行時,該表達式將產生對HashMap類實例的引用。” 只要編譯器可以精確地跟蹤您對該表達式結果的處理方式,它就可以保持知道確實是HashMap<Integer, String> ,但是HashMap<Integer, String>

現在,由於靜態類型系統的功能不足以跟蹤數組的組件類型上的類型參數(Java的數組類型是協變量的事實在這里發揮了重要作用),因此代碼被迫脫離靜態類型安全網絡。 關鍵的觀察是,這本身並不會使代碼不正確 ,而只會限制編譯器發現編程錯誤的能力。 這就是為什么Java允許您從原始類型到泛型類型進行未經檢查的強制轉換,盡管並非沒有警告,這標志着您已經離開了靜態類型安全的省份。

暫無
暫無

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

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