C#的泛型和Java的偽泛型


   C#的泛型和java的偽泛型,talk is cheap,show me the code

   C#泛型

        下面結果,C#里面會輸出false,如果這個還不能真正的說明C#的泛型是真的泛型,那就看下面這段代碼。

            List<Test> arr1 = new List<Test>();
            List<String> arr2 = new List<String>();
            Console.WriteLine(arr1.GetType());
            Console.WriteLine(arr2.GetType());
            Console.WriteLine(arr1.GetType()==arr2.GetType());  

  

  下面這段代碼,我們通過反射執行Add方法,即使代碼編譯通過,但是執行的時候會報錯。

        List<String> strList = new List<string>();
        strList.Add("test");

        Type type = strList.GetType();

            type.GetMethod("Add").Invoke(strList, new object[] { 123 
            });
            foreach (var t in strList)
            {
                Console.WriteLine(t);
            }

  

  上面這兩段代碼證明了,C#的泛型是真的泛型,因為它確實在IL方法中,給了我們一個真實存在的類。

  Java泛型

  java泛型會進行類型擦除,是偽泛型。因為在java生成的字節碼中,最后泛型會背Object替代。

       java中,下面這些代碼都不會報錯,足以證明,偽泛型。

        System.out.println("java中的假泛型");
        ArrayList<Integer>  arr1=new ArrayList<>();
        ArrayList<String> arr2=new ArrayList<>();
        System.out.println(arr1.getClass()==arr2.getClass());

        System.out.println("類型擦除");
        ArrayList<Integer> list = new ArrayList<Integer>();

        list.add(1);  //這樣調用 add 方法只能存儲整形,因為泛型類型的實例為 Integer

        list.getClass().getMethod("add", Object.class).invoke(list, "asd");

        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

  C#的泛型是不是真的那么好

    可能有同學會問,C#如果給每個泛型都搞上一個類(在中間代碼中),那DLL/EXE會不會變得非常大,從而影響性能呢,是的,我們想到了的,CLR的設計者也想到了。

           1、如果為特定類型的實參調用了一個方法,以后相同類型的實參調用這個方法,CLR只會為這個方法進行組合編譯一次。比如一個程序集使用了List<DateTime> ,一個完全不同的程序集(加載到同一個AppDomain中)也是用List<Datetime>,CLR只為會為List<DateTime>編譯一次。

          2、CLR還認為所有引用類型的實參都完全相同,所以代碼可以共享,因為引用類型都是在堆上了,因為堆上的東西,都是以對象指針的形式操縱。如果是值類型的呢,就需要專門為每個值類型生成本機代碼,因為值類型是位於內存棧上的,值類型的大小不固定,即使大小一樣,也沒辦法共享代碼,因為可能要用到不同的CPU的指令來進行操作 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM