以前没作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