亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

輕松掌握 Java 泛型 (第 2 部分)

2019-11-18 13:15:13
字體:
來源:轉載
供稿:網友

  J2SE 1.5 — 代號為“Tiger” — 計劃在 2003 年年底發布,它將包括泛型類型(如在 JSR-14 原型編譯器中預先展示的那樣,現在可下載獲得)。在第 1 部分中,我們討論了泛型類型的基礎知識,以及為什么它們是對 java 語言的一個重要且迫切需要的補充。我們還說明了為 Tiger 制定的泛型類型的實現怎么會包含數個“缺陷”,這些缺陷限制了可以使用泛型類型的上下文。
  
  為了幫助新程序員有效地使用泛型類型,我將具體說明到底泛型類型的哪些用法在 Tiger 和 JSR-14 中是被禁止的,并將說明為什么這些限制是 JSR-14(理所當然還有 Tiger)為了在 JVM 上兼容地實現泛型類型所使用的實現策略的必然結果。
  
  泛型類型的限制
  讓我們先查閱一下 Tiger 和 JSR-14 中泛型類型的使用限制:
  
  不應在靜態成員中引用封閉類型參數。
  不能用基本類型實例化泛型類型參數。
  不能在數據類型轉換或 instanceof 操作中使用“外露”類型參數。
  不能在 new 操作中使用“外露”類型參數。
  不能在類定義的 implements 或 extends 子句中使用“外露”類型參數。
  為什么會有這些限制呢?這要歸因于 Tiger 和 JSR-14 為在 JVM 上實現泛型類型所使用的機制。由于 JVM 根本不支持泛型類型,所以這些編譯器“耍了個花招”,使得似乎存在對泛型類型的支持 — 它們用泛型類型信息檢查所有的代碼,但隨即“擦除”所有的泛型類型并生成只包含普通類型的類文件。
  
  例如,將象 List< T> 這樣的泛型類型擦除得只剩下 List?!巴饴丁鳖愋蛥?— 單獨出現而不是位于某個類型中的類型參數(如類 List< T> 中的類型參數 T)— 被簡單地擦除成它們的上界(就 T 而言,其上界就是 Object)。
  
  這一技術的功能極其強大;我們可以使幾乎所有泛型類型的精度得到增強,但又與 JVM 保持兼容。事實上,我們甚至可以交替地使用非泛型的舊類(比如 List)和其對應的泛型類(List< T>);兩者在運行時看起來是一樣的。
  
  遺憾的是,正如以上的限制所示,獲得這一功能是有代價的。以這種方式進行擦除在類型系統中引入了缺陷,這些缺陷限制我們使用泛型類型的安全性。
  
  為了幫助說明每種限制,我們查閱會出現這些限制的示例。在本文中,我們將討論前三個限制。與后兩個限制有關的問題過于復雜,因而需要更深入的研究,留待下一篇文章討論。
  
  靜態成員中的封閉類型參數
  編譯器完全禁止在靜態方法和靜態內部類中引用封閉類型參數。所以,舉例來說,以下代碼在 Tiger 中就是非法的:
  
  清單 1. 在靜態上下文中非法引用封閉類型參數 class C< T> {
   static void m() {
    T t;
   }
  
   static class D {
    C< T> t;
   }
  }
  
  當編譯這一代碼時,會生成兩個錯誤:
  
  在靜態方法 m 中非法引用 T 的錯誤
  在靜態類 D 中非法引用 T 的錯誤
  當定義靜態字段時,情況變得更加復雜。在 JSR-14 和 Tiger 中,在泛型類的所有實例中共享該類中的靜態字段?,F在,在 JSR-14 編譯器 1.0 和 1.2 中,假如您在靜態字段聲明中引用類型參數,編譯器不會報錯,但它本應該這么做。字段被共享這一事實很輕易在運行時導致希奇的錯誤,如在不包含數據類型轉換的代碼中出現 ClassCastException。
  
  例如,以下程序將在這兩個版本的 JSR-14 下通過編譯而沒有任何警告:
  
  清單 2. 在靜態字段中對封閉類型參數的有問題的引用 class C< T> {
   static T member;
  
   C(T t) { member = t; }
  
   T getMember() { return member; }
  
   public static void main(String[] args) {
    C< String> c = new C< String>("test");
    System.out.PRintln(c.getMember().toString());
    new C< Integer>(new Integer(1));
    System.out.println(c.getMember().toString());
   }
  }
  
  請注重,每次分配類 C 的實例時,都要重新設置靜態字段 member。而且,它被設置成的對象類型取決于 C 的實例的類型!在所提供的 main 方法中,第一個實例 c 是 C< String> 類型。而第二個是 C< Integer> 類型。每當從 c 訪問 member 這一共享靜態字段時,總是假定 member 的類型是 String。但是,在分配了類型為 C< Integer> 的第二個實例之后,member 的類型是 Integer。
  
  運行 C 的 main 方法的結果可能會讓您吃驚 — 它將發出一個 ClassCastException!源代碼根本沒有包含任何數據類型轉換,怎么會這樣呢?事實證實編譯器確實在編譯階段將數據類型轉換插入到代碼中,這樣做是為了解決類型擦除會降低某些表達式的類型的精度這一事實。這些數據類型轉換被期望能夠成功,但在本例中卻沒有成功。
  
  應該認為 JSR-14 1.0 和 1.2 的這一非凡“功能”是個錯誤。它破壞了類型系統的健全性,或者可以說,它破壞了類型系統應該和程序員達成的“基本契約”。象對靜態方法和類所做的那樣,只要防止程序員在靜態字段中引用泛型類型,情況就會好很多。
  
  請注重答應這種有潛在“爆炸性”的代碼存在所帶來的問題并不是程序員有意在自己的代碼中覆蓋類型系統。問題是程序員可能會無意中編寫這樣的代碼(比如,由于“復制和粘貼”操作,錯誤地在字段聲明中包括靜態修飾符)。
  
  類型檢查器應該能幫助程序員從這些類型的錯誤中恢復,但對于靜態字段而言,類型系統實際上會使程序員更迷惑。當未使用數據類型轉換的代碼中顯示的唯一錯誤就是 ClassCastException 時,我們應如何診斷這樣的錯誤?對于不清楚 Tiger 中泛型類型所用的實現方案而又恰好假定類型系統合理運行的程序員而言,情況更糟。因為在這樣的情況下,類型系統不是合理地運行。
  
  幸運的是,JSR-14 的最新版本(1.3)公布在靜態字段中使用類型參數是不合法的。因此,我們有理由期待在 Tiger 的靜態字段中使用類型參數也是不合法的。
  
  泛型類型參數和基本類型
  和我們剛才討論的不同,這一限制沒有同樣的潛在缺陷,但它會使您的代碼非常冗長。例如,在 java.util.Hashtable 的泛型版本中,有兩種類型參數:用于 Key 類型的和用于 Value 類型的。因此,假如我們想要一個將 String 映射到 String 的 Hashtable,我們可以用表達式 new Hashtable< String, String>() 指定新的實例。但是,假如我們想要一個將 String 映射到 int 的 Hashtable,我們只能創建 Hashtable< String, Integer> 的實例,并將所有的 int 值包裝在 Integer 中。
  
  同樣,Tiger 在這方面當然也是由所用的實現方案得到的。既然類型參數被擦除為它們的界限,而界限不能是基本類型,所以一旦類型被擦除,則對基本類型的實例化會完全沒有意義。
  
  數據類型轉換或 instanceof 操作中的“外露”參數
  回想一下,對于“外露”類型參數,我們是指在詞匯上單獨出現的類型參數,而不是更大類型的語法子組件。例如,C< T> 不是“外露”類型參數,但(在 C 主體中)T 是。
  
  假如在代碼中對“外露”類型參數進行數據類型轉換或 instanceof 操作,則編譯器將發出名為“unchecked”的警告。例如,以下代碼將生成警告:Warning: unchecked cast to type T:
  
  清單 3. 帶 unchecked 操作的泛型代碼 import java.util.Hashtable;
  interface Registry {
   public void register(Object o);
  }
  class C< T> implements Registry {
   int counter = 0;
   Hashtable< Integer, T> values;
  
   public C() {
    values = new Hashtable< Integer, T>();
   }
  
   public void register(Object o) {
    values.put(new Integer(counter), (T)o);
    counter++;
   }
  }
  
  您應該嚴厲地對待這些警告,因為它們說明您的代碼在運行時會表現得非常希奇。事實上,它們會使得診斷代碼變得極為困難。在以前的代碼中,我們認為假如對實例 C< JFrame> 調用 register("test"),會發出 ClassCastException。但并非如此;計算將繼續,就仿佛數據類型轉換成功了一樣,然后在進一步進行計算時發出錯誤,或者更糟:用遭破壞的數據完成計算,但不向外發出任何錯誤信號。同樣,對“外露”類型參數的 instanceof 檢查將在編譯時產生“unchecked”警告,而且檢查將不會如期在運行時進行。
  
  雙刃劍
  那么,這里到底發生了什么?因為 Tiger 依靠類型擦除,所以數據類型轉換和 instanceof 測試中的外露類型參數被“擦除”為它們的上界(在前面的例子中,那將是類型 Object)。因此,對類型參數的數據類型轉換將變成對參數上界的轉換。
  
  同樣,instanceof 將檢查操作數是否是參數界限的 instanceof。那根本不是我們打算做的,假如是的話,我們完全可以顯式地強制轉換為界限。因此,通常應避免對類型參數使用數據類型轉換和 instanceof 檢查。
  
  然而,有時為了編譯代碼,您必須依靠對類型參數的數據類型轉換。假如是這樣的情況,只要記住,在代碼的那一部分中,類型檢查不保險 — 要靠自己。
  
  盡管泛型類型是制作健壯代碼的強大武器,但我們已經演示了誤用它們會使代碼不再健壯而且極難診斷和修正。下次,我們將介紹 Tiger 中泛型類型的后兩個限制,并討論試圖在泛型 Java 類型系統中包括它們時必定會出現的一些問題。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品久久久久久久久久久久| 亚洲一区二区三区xxx视频| 亚洲美女在线观看| 亚洲国产精品热久久| 久久久女人电视剧免费播放下载| 午夜精品久久久久久久99热| 欧美日韩在线另类| 久久久久久久国产精品| 亚洲第一区第一页| 亚洲第一区第一页| 狠狠躁夜夜躁人人爽超碰91| 欧美亚洲国产视频| 国产精品久久久久久av下载红粉| 欧美亚洲激情在线| 亚洲精品久久久久中文字幕二区| 韩国一区二区电影| 欧美性受xxxx黑人猛交| 成人免费看吃奶视频网站| 91理论片午午论夜理片久久| 国产成人久久久精品一区| 精品久久久久久久久中文字幕| 国产精品 欧美在线| 都市激情亚洲色图| 欧美日韩国产色视频| 亚洲天堂精品在线| 亚洲成人国产精品| 中文字幕久久久av一区| 亚洲一区二区三区xxx视频| www.久久色.com| 久久色在线播放| 久久久国产在线视频| 91亚洲精品在线观看| 青青草成人在线| 91久久国产精品91久久性色| 欧美日韩在线视频一区二区| 久久精品久久久久久国产 免费| 国产精品91久久久久久| 国产精品久久久久91| 国产精品久久久久久影视| 日韩高清人体午夜| 久久精品国亚洲| 91精品久久久久久久久中文字幕| 青草青草久热精品视频在线观看| 亚洲成色999久久网站| 欧美精品18videos性欧| 一区二区三区无码高清视频| 国产91露脸中文字幕在线| 亚洲男人av在线| 亚洲一区二区国产| 国产成人久久久精品一区| 久久久久久91| 亚洲高清在线观看| 一区二区三区四区精品| 欧洲美女7788成人免费视频| 永久免费看mv网站入口亚洲| 成人久久精品视频| 成人动漫网站在线观看| 欧美视频中文字幕在线| 亚洲精品欧美日韩专区| 热99精品只有里视频精品| 欧美精品做受xxx性少妇| 伊人一区二区三区久久精品| 亚洲欧洲av一区二区| 精品国产自在精品国产浪潮| 亚洲精品成人久久电影| 日韩精品免费在线视频观看| 国产精品一香蕉国产线看观看| 国产精品视频26uuu| 色噜噜狠狠狠综合曰曰曰| 亚洲自拍偷拍色片视频| 国产精品日韩精品| 亚洲人成在线免费观看| 456国产精品| 92国产精品视频| 欧美在线欧美在线| 国产精品一区久久| 国产做受高潮69| 91在线精品播放| 欧美精品videos性欧美| 欧美日韩国产麻豆| 亚洲老司机av| 欧美精品videos性欧美| 日韩小视频在线| 精品精品国产国产自在线| 国产精品美女999| 国产精品入口免费视| 国产一区二中文字幕在线看| 在线视频欧美性高潮| 亚洲色图校园春色| 欧美精品在线看| 国产精品99久久久久久久久| 国产剧情日韩欧美| 精品国产一区二区在线| 日韩三级影视基地| 欧美电影第一页| 中文字幕日韩av电影| 色婷婷亚洲mv天堂mv在影片| 高清欧美电影在线| 亚洲欧美日韩区| 国产不卡在线观看| 欧美日韩美女在线观看| 日本精品久久电影| 国产精品自产拍在线观看| 久久中文字幕在线| 国产成人高潮免费观看精品| 久久伊人精品一区二区三区| 久久夜精品香蕉| 久久久91精品国产| 在线日韩日本国产亚洲| 欧美激情女人20p| 欧美日韩黄色大片| 久久久精品在线观看| 欧美电影电视剧在线观看| 在线日韩日本国产亚洲| 国产在线观看91精品一区| 伊人伊成久久人综合网小说| 亚洲第一福利在线观看| 国产精品久久97| 美女撒尿一区二区三区| 亚洲免费精彩视频| 国产一区二区三区高清在线观看| 国产精品久久久久久久久粉嫩av| 国产亚洲欧美aaaa| 国产精品电影在线观看| 日韩欧美高清视频| 亚洲女人天堂成人av在线| 久久精品国产欧美激情| 国产91亚洲精品| 日韩欧美精品在线观看| 欧美乱人伦中文字幕在线| 91av在线网站| 亚洲国产中文字幕久久网| 一区二区三区国产在线观看| 国产精品中文字幕在线观看| 国产日韩欧美视频在线| 夜夜狂射影院欧美极品| 欧美一区二区视频97| 亚洲人成电影网站色…| 久久视频这里只有精品| 日韩av资源在线播放| 在线免费看av不卡| 国产精品中文字幕久久久| 宅男66日本亚洲欧美视频| 91九色国产社区在线观看| 日韩中文字幕在线观看| 日本久久亚洲电影| 欧洲成人在线视频| 国产日韩欧美综合| 国产精品高清在线| 欧美剧在线观看| 欧美专区日韩视频| 77777亚洲午夜久久多人| 久久噜噜噜精品国产亚洲综合| 97碰在线观看| 国产综合视频在线观看| 亚洲少妇激情视频| 日本欧美在线视频| 久久久免费观看视频| 久久久精品日本| 俺去啦;欧美日韩| 亚洲成人久久久久| 亚洲黄色www网站| 久久久久久久久久久91| 精品国产91乱高清在线观看|