以前沒作java的時候就一直據說java的泛型是假泛型,可是一直沒有去了解過,最近作了java發現不少和C#泛型不一樣的地方,好比:java
T t = new T(); //這段代碼在C#中是很正常的一段代碼,可是在我寫java的時候發現報錯了
what fuck?爲何這個會報錯?那我想return new T呢?jvm
後來在網上找到了答案:Java的泛型在編譯的時候會使用「類型擦除」來實現泛型,也就是說編譯後的T會變成Object:spa
public class Class1<K,V> { private Dictionary<K, V> keyValuePairs = new Dictionary<K, V>(); public V Get(K k) { return keyValuePairs.GetValueOrDefault(k); } public void Set(K k,V v) { keyValuePairs.Add(k, v); } }
這段代碼,java編譯後的字節碼和C#編譯後的IL能夠看出來這個問題的答案:code
能夠看到,IL是的TKey是在運行時確切的包含了TKey TValue的信息的,CLR會根據運行時的不一樣狀態生成不一樣的類型。而Java是直接將泛型轉換成了Object。這就很操蛋了,那這段代碼在Java中怎麼實現呢:對象
public class Cache<TKey, TValue> { public static TValue Instance; } public class Factory { public static string Create<TKey>() { if (Cache<TKey, string>.Instance == null) { Cache<TKey, string>.Instance = // some expensive computation } return Cache<TKey, string>.Instance; } }
TKey在運行時類型就已經被擦除了,假設這裏的字典/hashmap是一個<int,object>類型的,這段代碼在JVM平臺上建立的應該是一個hashmap對象,而且不會區分<int,object><int,string>,由於對於jvm來講hashmap<int,object>,hashmap<int,string>都是hashmap,並無什麼區別。blog