91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

.NET中的泛型和Java泛型中的類型擦除

發布時間:2020-07-15 07:26:02 來源:網絡 閱讀:1041 作者:cnn237111 欄目:編程語言

開放類型和閉合類型

.NET把帶有類型參數的類型看做一個新的類型,CLR將為這些類型創建內部類型對象,帶有類型參數的類型可以是類,結構,接口和委托。但是,一個帶有類型參數的類型稱為開放類型,CLR不允許開放類型實例化(就好比不允許接口實例化一樣)。

當代碼中引用了泛型類型,代碼里可以指定一組泛型類型參數。如果傳入實際的數據類型,那么這個類型就成為閉合類型,CLR允許實例化閉合類型。然而,也有可能代碼引用了泛型類型,但未指定泛型類型參數,這就在CLR中創建了一個新的開放類型,這種類型無法實例化,看一個例子。

  1. internal sealed class DictionaryStringKey<TValue> :Dictionary<String, TValue> 
  2.         { 
  3.         } 
  4.         static void Main(string[] args) 
  5.         { 
  6.             Object o = null
  7.             // Dictionary<,> 有2個類型參數的開放類型 
  8.             Type t = typeof(Dictionary<,>); 
  9.             // 創建實例會失敗 
  10.             o = CreateInstance(t); 
  11.             Console.WriteLine(); 
  12.             // DictionaryStringKey<>有一個類型參數的開發類型 
  13.             t = typeof(DictionaryStringKey<>); 
  14.             // 創建該類型的實例也會失敗 
  15.             o = CreateInstance(t); 
  16.             Console.WriteLine(); 
  17.             // DictionaryStringKey<Guid> 是閉合類型 
  18.             t = typeof(DictionaryStringKey<Guid>); 
  19.             // 創建成功 
  20.             o = CreateInstance(t); 
  21.             // 輸出類型名字 
  22.             Console.WriteLine("Object type=" + o.GetType()); 
  23.         } 
  24.         private static Object CreateInstance(Type t) 
  25.         { 
  26.             Object o = null
  27.             try 
  28.             { 
  29.                 //使用默認的構造函數來創造該類型的實例 
  30.                 o = Activator.CreateInstance(t); 
  31.                 Console.Write("Created instance of {0}", t.ToString()); 
  32.             } 
  33.             catch (ArgumentException e) 
  34.             { 
  35.                 Console.WriteLine(e.Message); 
  36.             } 
  37.             return o; 
  38.         } 

運行結果:

.NET中的泛型和Java泛型中的類型擦除

Activator.CreateInstance創建實例的時候,會提示你該類型包含泛型參數。

輸出中,可以看到類型名稱后跟著反引號(`)以及一個數字。這個數字即類型中的類型參數的數量。比如泛型Dictionary類是2,因為它需要2個類型參數來指示TKey和TValue。DictionaryStringKey類只有1個因為它只需要指明1個類型TValue。

.NET中的類型

.net中,除了實例構造器,CLR也支持類型構造器(也稱作靜態夠器,類夠在其或者類型初始化器)。類型構造器可以應用于接口(c#中不支持),引用類型(class)和值類型(struct),和實例構造器初始化類型的實例一樣,類型構造器用來初始化類型的一些狀態,類型的構造器如果有的話 只可能有1個,并且是無參的。可以參考之前的文章。

http://cnn237111.blog.51cto.com/2359144/576533

由于CLR保證了類型初始化器只執行一次,并且是線程安全的,因此類型初始化器適用于用在單例模式中對單例對象的初始化。

類型中的靜態字段可以認為是類型的一部分,而類型中的非靜態字段可以認為是實例對象的一部分。當JIT編譯器把IL語言轉換成本地的CPU指令的時候,會遇到很多類型(比如自定義的class),CLR為了能正確的加載包含這些類型的程序集,它會通過程序集的元數據,抽取出類型的信息,然后創建這些類型的數據數據結構。這些數據結構作為對象存放在堆中。堆中所有的對象都有2個成員,類型對象指針和同步塊索引。類型中定義的靜態字段也包含在數據結構對象中。類的實例對象都共享類型對象中同一個靜態字段。如下圖:方框中的Manager是類型對象,靜態字段存在于類型對象中。實例對象由橢圓框表示,指向類型對象。

.NET中的泛型和Java泛型中的類型擦除

對于.NET泛型來說,每一個閉合類型都有自己的靜態字段。也就是說List<>和List<String>中的靜態字段是互相獨立的。同樣的,如果泛型類型定義了一個靜態構造器,這些構造器也是按照各自的閉合類型運行。也就是說,List<DateTime>和List<String>有自己獨立的靜態構造器。

  1. static void Main(string[] args) 
  2.         { 
  3.             bool issame = typeof(List<DateTime>) == typeof(List<string>); 
  4.             Console.WriteLine(issame); 
  5.             object o = Activator.CreateInstance(typeof(List<DateTime>)); 
  6.             Console.WriteLine(o.GetType()); 
  7.             o = Activator.CreateInstance(typeof(List<string>)); 
  8.             Console.WriteLine(o.GetType()); 
  9.         } 

運行結果如下:

.NET中的泛型和Java泛型中的類型擦除

Java泛型中的類型擦除

  經常聽人說起Java的泛型是偽泛型,因為在編譯或運行期間,java的JIT會對進行類型擦除。即JVM無法真正識別出泛型類型,因此在真正運行前會把泛型類型轉換成原始類型。因此,所有的泛型類型,本質上都共享同一個類型對象。比如List<Integer>類型在擦除后變成非泛型的List,這個List可以存放任何類型的數據。因此,Java在運行的時候,無法獲得類型。當然,使用反射也許可以知道,但是并不保證總是能夠得到類型。因此在Java代碼中,不同的泛型類型其實都是出自相同的類型。例如下面代碼:

  1. public static void main(String[] args) throws Exception { 
  2.   List<Integer> li = new ArrayList<Integer>(); 
  3.   List<Float> lf = new ArrayList<Float>(); 
  4.   boolean issame = li.getClass() == lf.getClass(); 
  5.   System.out.println(issame);//true 
  6.   Object o = li.getClass().newInstance(); 
  7.   System.out.println(o.getClass().getName());//java.util.ArrayList 
  8.   o = lf.getClass().newInstance(); 
  9.   System.out.println(o.getClass().getName());//java.util.ArrayList 

也正是由于代碼擦除,使得泛型類型本質上都是共享同一個類型對象,因此類型的靜態字段也是共享的。例如下面代碼:

  1. public class AtestClass<E> { 
  2. public static int i=0
  3. public AtestClass() 
  4. i++; 
  5.  
  6. ------------------ 
  7.  
  8. public static void main(String[] args) throws Exception { 
  9.    AtestClass<Integer> ai=new AtestClass<Integer>(); 
  10.    AtestClass<Float> af=new AtestClass<Float>(); 
  11.    System.out.println(AtestClass.i); 

最終運行的結果是2.


參考文檔:Microsoft.Press.CLR.via.Csharp.4th.Edition.Oct.2012.

https://en.wikipedia.org/wiki/Generics_in_Java.

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

宁河县| 辽源市| 曲阳县| 绩溪县| 嘉祥县| 沾益县| 信阳市| 时尚| 昭平县| 乐陵市| 黄龙县| 宿松县| 神木县| 天气| 宜阳县| 宜良县| 桦川县| 鄂伦春自治旗| 尚义县| 正镶白旗| 五大连池市| 宣汉县| 德格县| 高台县| 洛扎县| 鹤山市| 江门市| 庄河市| 沙雅县| 溆浦县| 凤城市| 普格县| 厦门市| 聂拉木县| 上蔡县| 香港| 简阳市| 松原市| 濮阳市| 独山县| 喀什市|