从C#到Java(泛型)

  之前没做java的时候就一直听说java的泛型是假泛型,但是一直没有去了解过,最近做了java发现很多和C#泛型不同的地方,比如:

T t = new T(); //这段代码在C#中是很正常的一段代码,但是在我写java的时候发现报错了

  what fuck?为什么这个会报错?那我想return new T呢?

  后来在网上找到了答案:Java的泛型在编译的时候会使用“类型擦除”来实现泛型,也就是说编译后的T会变成Object:

    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可以看出来这个问题的答案:

 

 

可以看到,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,并没有什么区别。

posted @ 2019-07-04 10:47  鹿麋~  阅读(685)  评论(0编辑  收藏  举报