麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

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

2019-11-18 13:15:13
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  J2SE 1.5 - 代號(hào)為 Tiger - 計(jì)劃在 2003 年年底發(fā)布。我一直都熱衷于盡可能多地收集有關(guān)即將推出的新技術(shù)的預(yù)告信息,因此我將撰寫一系列的文章,討論可從 V1.5 中獲得的新的和經(jīng)過(guò)重組的特性,本文是第一篇。我非凡想談?wù)劮盒皖愋筒⒅攸c(diǎn)講述在 Tiger 中為了支持它們而進(jìn)行的更改和調(diào)整。
  
  在許多方面,Tiger 肯定是迄今為止在 java 編程方面(包括對(duì)源語(yǔ)言語(yǔ)法的重大擴(kuò)展)所取得的最大進(jìn)步。Tiger 中計(jì)劃進(jìn)行的最顯著的變化是添加泛型類型,正如在 JSR-14 原型編譯器中所預(yù)先展示的那樣(您可以立即免費(fèi)下載該編譯器;請(qǐng)參閱參考資料)。
  
  讓我們從介紹泛型類型是什么以及添加了什么特性來(lái)支持它們開(kāi)始吧。
  
  數(shù)據(jù)類型轉(zhuǎn)換和錯(cuò)誤
  為理解泛型類型為何如此有用,我們要將注重力轉(zhuǎn)向 Java 語(yǔ)言中最輕易引發(fā)錯(cuò)誤的因素之一 - 需要不斷地將表達(dá)式向下類型轉(zhuǎn)換(downcast)為比其靜態(tài)類型更為具體的數(shù)據(jù)類型(請(qǐng)參閱參考資料中的“The Double Descent bug pattern”,以了解進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換時(shí),可能會(huì)碰到的麻煩的某些方面)。
  
  程序中的每個(gè)向下類型轉(zhuǎn)換對(duì)于 ClassCastException 而言都是潛在的危險(xiǎn),應(yīng)當(dāng)盡量避免它們。但是在 Java 語(yǔ)言中它們通常是無(wú)法避免的,即便在設(shè)計(jì)優(yōu)良的程序中也是如此。
  
  在 Java 語(yǔ)言中進(jìn)行向下類型轉(zhuǎn)換最常見(jiàn)的原因在于,經(jīng)常以專用的方式來(lái)使用類,這限制了方法調(diào)用所返回的參數(shù)可能的運(yùn)行時(shí)類型。例如,假定往 Hashtable 中添加元素并從中檢索元素。那么在給定的程序中,被用作鍵的元素類型和存儲(chǔ)在散列表中的值類型,將不能是任意對(duì)象。通常,所有的鍵都是某一特定類型的實(shí)例。同樣地,存儲(chǔ)的值將共同具有比 Object 更具體的公共類型。
  
  但是在目前現(xiàn)有的 Java 語(yǔ)言版本中,不可能將散列表的特定鍵和元素聲明為比 Object 更具體的類型。在散列表上執(zhí)行插入和檢索操作的類型特征符告訴我們只能插入和刪除任意對(duì)象。例如,put 和 get 操作的說(shuō)明如下所示:
  
  清單 1. 插入/檢索類型說(shuō)明表明只能是任意對(duì)象
  
  class Hashtable {
   Object put(Object key, Object value) {...}
   Object get(Object key) {...}
   ...
  }
  
  因此,當(dāng)我們從類 Hashtable 的實(shí)例檢索元素時(shí),比如,即使我們知道在 Hashtable 中只放了 String,而類型系統(tǒng)也只知道所檢索的值是 Object 類型。在對(duì)檢索到的值進(jìn)行任何特定于 String 的操作之前,必須將它強(qiáng)制轉(zhuǎn)換為 String,即使是將檢索到的元素添加到同一代碼塊中,也是如此!
  
  清單 2. 將檢索到的值強(qiáng)制轉(zhuǎn)換成 String
  
  import java.util.Hashtable;
  class Test {
   public static void main(String[] args) {
    Hashtable h = new Hashtable();
    h.put(new Integer(0), "value");
    String s = (String)h.get(new Integer(0));
    System.out.PRintln(s);
   }
  }
  
  請(qǐng)注重 main 方法主體部分的第三行中需要進(jìn)行的數(shù)據(jù)類型轉(zhuǎn)換。因?yàn)?Java 類型系統(tǒng)相當(dāng)薄弱,因此代碼會(huì)因象上面那樣的數(shù)據(jù)類型轉(zhuǎn)換而漏洞百出。這些數(shù)據(jù)類型轉(zhuǎn)換不僅使 Java 代碼變得更加拖沓冗長(zhǎng),而且它們還降低了靜態(tài)類型檢查的價(jià)值(因?yàn)槊總€(gè)數(shù)據(jù)類型轉(zhuǎn)換都是一個(gè)選擇忽略靜態(tài)類型檢查的偽指令)。我們?cè)撊绾螖U(kuò)展該類型系統(tǒng),從而不必回避它呢?
  
  用泛型類型來(lái)解決問(wèn)題!
  要消除如上所述的數(shù)據(jù)類型轉(zhuǎn)換,有一種普遍的方法,就是用泛型類型來(lái)增大 Java 類型系統(tǒng)。可以將泛型類型看作是類型“函數(shù)”;它們通過(guò)類型變量進(jìn)行參數(shù)化,這些類型變量可以根據(jù)上下文用各種類型參數(shù)進(jìn)行實(shí)例化。
  
  例如,與簡(jiǎn)單地定義類 Hashtable 不同,我們可以定義泛型類 Hashtable< Key, Value>,其中 Key 和 Value 是類型參數(shù)。除了類名后跟著尖括號(hào)括起來(lái)的一系列類型參數(shù)聲明之外,在 Tiger 中定義這樣的泛型類的語(yǔ)法和用于定義普通類的語(yǔ)法很相似。例如,可以按照如下所示的那樣定義自己的泛型 Hashtable 類:
  
  清單 3. 定義泛型 Hashtable 類
  
  class Hashtable< Key, Value> { ... }
  
  然后可以引用這些類型參數(shù),就像我們?cè)陬惗x主體內(nèi)引用普通類型那樣,如下所示:
  
  清單 4. 像引用普通類型那樣引用類型參數(shù) class Hashtable< Key, Value> {
   ...
   Value put(Key k, Value v) {...}
   Value get(Key k) {...}
  }
  
  類型參數(shù)的作用域就是相應(yīng)類定義的主體部分(除了靜態(tài)成員之外)(在下一篇文章中,我們將討論為何 Tiger 實(shí)現(xiàn)中有這樣的“怪習(xí)”,即必須對(duì)靜態(tài)成員進(jìn)行此項(xiàng)限制。請(qǐng)留意!)。
  
  創(chuàng)建一個(gè)新的 Hashtable 實(shí)例時(shí),必須傳遞類型參數(shù)以指定 Key 和 Value 的類型。傳遞類型參數(shù)的方式取決于我們打算如何使用 Hashtable。在上面的示例中,我們真正想要做的是創(chuàng)建 Hashtable 實(shí)例,它只將 Integer 映射為 String。可以用新的 Hashtable 類來(lái)完成這件事:
  
  清單 5. 創(chuàng)建將 Integer 映射為 String 的實(shí)例
  
  import java.util.Hashtable;
  class Test {
   public static void main(String[] args) {
    Hashtable< Integer, String> h = new Hashtable< Integer, String>();
    h.put(new Integer(0), "value");
    ...
   }
  }
  
  現(xiàn)在不再需要數(shù)據(jù)類型轉(zhuǎn)換了。請(qǐng)注重用來(lái)實(shí)例化泛型類 Hashtable 的語(yǔ)法。就像泛型類的類型參數(shù)用尖括號(hào)括起來(lái)那樣,泛型類型應(yīng)用程序的參數(shù)也是用尖括號(hào)括起來(lái)的。
  
  清單 6. 除去不必要的數(shù)據(jù)類型轉(zhuǎn)換
  
  ...
  String s = h.get("key");
  System.out.println(s);
  
  當(dāng)然,程序員若只是為了能使用泛型類型而必須重新定義所有的標(biāo)準(zhǔn)實(shí)用程序類(比如 Hashtable 和 List)的話,則可能會(huì)是一項(xiàng)浩大的工程。幸好,Tiger 為用戶提供了所有 Java 集合類的泛型版本,因此我們不必自己動(dòng)手來(lái)重新定義它們了。此外,這些類能與舊代碼和新的泛型代碼一起無(wú)縫工作(下個(gè)月,我們會(huì)說(shuō)明如何做到這一點(diǎn))。
  
  Tiger 的基本類型限制
  Tiger 中類型變量的限制之一就是,它們必須用引用類型進(jìn)行實(shí)例化 - 基本類型不起作用。因此,在上面這個(gè)示例中,無(wú)法完成創(chuàng)建從 int 映射到 String 的 Hashtable。
  
  這很遺憾,因?yàn)檫@意味著只要您想把基本類型用作泛型類型的參數(shù),您就必須把它們組裝為對(duì)象。另一方面,當(dāng)前的這種情況是最糟的;您不能將 int 作為鍵傳遞給 Hashtable,因?yàn)樗械逆I都必須是 Object 類型。
  
  我們真正想看到的是,基本類型可以自動(dòng)進(jìn)行包裝(boxing)和解包裝(unboxing),類似于用 C# 所進(jìn)行的操作(或者比后者更好)。遺憾的是,Tiger 不打算包括基本類型的自動(dòng)包裝(但是人們可以一直期待 Java 1.6 中出現(xiàn)該功能!)。
  
  受限泛型
  有時(shí)我們想限制可能出現(xiàn)的泛型類的類型實(shí)例化。在上面這個(gè)示例中,類 Hashtable 的類型參數(shù)可以用我們想用的任何類型參數(shù)進(jìn)行實(shí)例化,但是對(duì)于其它某些類,我們或許想將可能的類型參數(shù)集限定為給定類型范圍內(nèi)的子類型。
  
  例如,我們可能想定義泛型 ScrollPane 類,它引用普通的帶有滾動(dòng)條功能的 Pane。被包含的 Pane 的運(yùn)行時(shí)類型通常會(huì)是類 Pane 的子類型,但是靜態(tài)類型就只是 Pane。
  
  有時(shí)我們想用 getter 檢索被包含的 Pane,但是希望 getter 的返回類型盡可能具體些。我們可能想將類型參數(shù) MyPane 添加到 ScrollPane 中,該類型參數(shù)可以用 Pane 的任何子類進(jìn)行實(shí)例化。然后可以用這種形式的子句:extends Bound 來(lái)說(shuō)明 MyPane 的聲明,從而來(lái)設(shè)定 MyPane 的范圍:
  
  清單 7. 用 extends 子句來(lái)說(shuō)明 MyPane 聲明
  
  class ScrollPane< MyPane extends Pane> { ... }
  
  當(dāng)然,我們可以完全不使用顯式的范圍,只要能確保沒(méi)有用不適當(dāng)?shù)念愋蛠?lái)實(shí)例化類型參數(shù)。
  
  為什么要自找麻煩在類型參數(shù)上設(shè)定范圍呢?這里有兩個(gè)原因。首先,范圍使我們?cè)黾恿遂o態(tài)類型檢查功能。有了靜態(tài)類型檢查,就能保證泛型類型的每次實(shí)例化都符合所設(shè)定的范圍。
  
  其次,因?yàn)槲覀冎李愋蛥?shù)的每次實(shí)例化都是這個(gè)范圍之內(nèi)的子類,所以可以放心地調(diào)用類型參數(shù)實(shí)例出現(xiàn)在這個(gè)范圍之內(nèi)的任何方法。假如沒(méi)有對(duì)參數(shù)設(shè)定顯式的范圍,那么缺省情況下范圍是 Object,這意味著我們不能調(diào)用范圍實(shí)例在 Object 中未曾出現(xiàn)的任何方法。
  
  多態(tài)方法
  除了用類型參數(shù)對(duì)類進(jìn)行參數(shù)化之外,用類型參數(shù)對(duì)方法進(jìn)行參數(shù)化往往也同樣很有用。泛型 Java 編程用語(yǔ)中,用類型進(jìn)行參數(shù)化的方法被稱為多態(tài)方法(Polymorphic method)。
  
  多態(tài)方法之所以有用,是因?yàn)橛袝r(shí)候,在一些我們想執(zhí)行的操作中,參數(shù)與返回值之間的類型相關(guān)性原本就是泛型的,但是這個(gè)泛型性質(zhì)不依靠于任何類級(jí)的類型信息,而且對(duì)于各個(gè)方法調(diào)用都不相同。
  
  例如,假定想將 factory 方法添加到 List 類中。這個(gè)靜態(tài)方法只帶一個(gè)參數(shù),也將是 List 唯一的元素(直到添加了其它元素)。因?yàn)槲覀兿M?List 成為其所包含的元素類型的泛型,所以希望靜態(tài) factory 方法帶有類型變量 T 這一參數(shù)并返回 List< T> 的實(shí)例。
  
  但是我們確實(shí)希望該類型變量 T 能在方法級(jí)別上進(jìn)行聲明,因?yàn)樗鼤?huì)隨每次單獨(dú)的方法調(diào)用而發(fā)生改變(而且,正如我在下一篇文章中將討論的那樣,Tiger 設(shè)計(jì)的“怪習(xí)”規(guī)定靜態(tài)成員不在類級(jí)類型參數(shù)的范疇之內(nèi))

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 性高湖久久久久久久久aaaaa | www.狠狠插.com| 免费国产自久久久久三四区久久 | 久久久久久久久久综合 | 羞羞视频一区 | 在线观看免费毛片视频 | xxxxhd73国产| 精品国产一区二区三区免费 | 久久精品国产一区二区电影 | 奶子吧naiziba.cc免费午夜片在线观看 | 久久最新免费视频 | 91网站免费在线观看 | 成年免费视频黄网站在线观看 | 日本网站在线看 | 欧美日韩亚洲另类 | 国产激情网 | aaaaa国产欧美一区二区 | 一区二区三区欧美在线 | 久久最新免费视频 | 久久免费观看一级毛片 | 国产精品视频免费网站 | 久久久午夜电影 | 亚洲欧美aⅴ | 色呦呦一区二区三区 | 国产午夜精品理论片a级探花 | 视频国产一区二区 | 久久久久久久久久久久久国产精品 | 精品国产一二区 | 免费国产在线精品 | 91成人亚洲 | 一区二区三级视频 | 亚洲影院在线播放 | 涩涩屋av | 久久最新网址 | 国产一区二区三区欧美 | 久色亚洲 | 国产激情视频在线 | 一区二区三区日韩在线 | 欧美成人免费一区二区三区 | 亚洲精品成人18久久久久 | 特色一级黄色片 |