<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    空間站

    北極心空

      BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
      15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks

                                                                       (一)
    JDK 5.0
    (也叫做 Java 5.0 或者 Tiger Java 來了一些大的化。其中最重要的化就是引入了泛型 —— 支持定義帶有抽象型參數(shù)的些參數(shù)由您在例化指定。泛型提高大型程序的型安全和可維護(hù)來了很大的潛力。

    泛型與 JDK 5.0 中其他幾個新的言特性相互協(xié)作,包括增強(qiáng) for 環(huán)(有叫做 foreach 或者 for/in 環(huán))、枚enumeration)和自裝箱(autoboxing)。

    本教程解了在 Java 言中引入泛型的機(jī),詳細(xì)了泛型的法和語義,并述了如何在自己的中使用泛型。

    本教程針對中高 Java 開發(fā),他想要了解針對泛型的新言支持是如何工作的。本教程假定者熟悉在 Java 言中開發(fā)接口和,并且具有基本的面向設(shè)計技能。

    泛型言特性只在 JDK 5.0 及以后版本中可用。如果您是基于早的 JDK 版本開發(fā)軟件,那在遷移到 JDK 5.0 或以后版本之前,將無法在代中使用泛型特性。

    了使用泛型,必具有一個 JDK 5.0 開發(fā)環(huán)境。可以從 Sun 公司的 Web 站點免 JDK 5.0 (http://java.sun.com/j2se/1.5.0/index.jsp)

    是泛型?

    泛型(Generic type 或者 generics)是 Java 言的型系統(tǒng)的一種擴(kuò)展,以支持創(chuàng)建可以按進(jìn)行參數(shù)化的。可以把型參數(shù)看作是使用參數(shù)指定的型的一個占位符,就像方法的形式參數(shù)是運行時傳遞的占位符一

    可以在集合框架(Collection framework)中看到泛型的機(jī)。例如,Map 您向一個 Map 添加任意象,即使最常的情況是在定映射(map)中保存某個特定型(比如 String)的象。

    Map.get() 被定義為返回 Object,所以一般必 Map.get() 結(jié)強(qiáng)轉(zhuǎn)換為期望的型,如下面的代所示:

    Map m = new HashMap();

    m.put("key", "blarg");

    String s = (String) m.get("key");

    程序通過編譯,必 get() 結(jié)強(qiáng)轉(zhuǎn)換為 String,并且希望結(jié)果真的是一個 String。但是有可能某人已經(jīng)映射中保存了不是 String 西,這樣,上面的代將會拋出 ClassCastException

    理想情況下,您可能會得出這樣一個點,即 m 是一個 Map,它將 String 映射到 String 可以您消除代中的強(qiáng)轉(zhuǎn)換,同時獲得一個附加的檢查層該檢查層可以防止有人將錯誤類型的保存在集合中。就是泛型所做的工作。

    泛型的好

    Java 言中引入泛型是一個大的功能增強(qiáng)。不僅語言、型系統(tǒng)編譯器有了大的化,以支持泛型,而且類庫進(jìn)行了大翻修,所以多重要的,比如集合框架,都已經(jīng)泛型化的了。這帶來了很多好

    型安全。泛型的主要目標(biāo)是提高 Java 程序的型安全。通知道使用泛型定量的型限制,編譯器可以在一個高得多的程度上驗證類型假設(shè)。沒有泛型,些假設(shè)就只存在于程序頭腦中(或者如果幸運的存在于代中)。

    Java 程序中的一流行技術(shù)是定義這樣的集合,即它的元素或是公共型的,比如“String 列表”或者“String String 的映射”。量聲明中捕獲這一附加的型信息,泛型允許編譯些附加的束。錯誤現(xiàn)在就可以在編譯時被捕了,而不是在運行當(dāng)作 ClassCastException 展示出來。將檢查從運行挪到編譯時有助于您更容易找到錯誤,并可提高程序的可靠性。

    消除強(qiáng)轉(zhuǎn)換泛型的一個附是,消除源代中的強(qiáng)轉(zhuǎn)換使得代更加可,并且減少了出機(jī)會。

    盡管減少強(qiáng)轉(zhuǎn)換可以降低使用泛型的代羅嗦程度,但是聲明泛型量會來相應(yīng)羅嗦。比下面兩個代例子。

    不使用泛型:

    List li = new ArrayList();

    li.put(new Integer(3));

    Integer i = (Integer) li.get(0);

    使用泛型:

    List<Integer> li = new ArrayList<Integer>();

    li.put(new Integer(3));

    Integer i = li.get(0);

    簡單的程序中使用一次泛型量不會降低羅嗦程度。但是于多次使用泛型量的大型程序來可以累起來降低羅嗦程度。

    潛在的性能收益。泛型為較大的優(yōu)來可能。在泛型的初始實現(xiàn)中,編譯器將強(qiáng)轉(zhuǎn)換(沒有泛型的,程序會指定強(qiáng)轉(zhuǎn)換)插入生成的字節(jié)碼中。但是更多型信息可用于編譯未來版本的 JVM 優(yōu)來可能。

    由于泛型的實現(xiàn)方式,支持泛型(幾乎)不需要 JVM 文件更改。所有工作都在編譯器中完成,編譯器生成似于沒有泛型(和強(qiáng)轉(zhuǎn)換所寫的代,只是更能確保型安全而已。


                                                                               (二)

    泛型用法的例子

    泛型的許多最佳例子都來自集合框架,因為泛型讓您在保存在集合中的元素上指定類型約束。考慮這個使用 Map 類的例子,其中涉及一定程度的優(yōu)化,即 Map.get() 返回的結(jié)果將確實是一個 String

    Map m = new HashMap();

    m.put("key", "blarg");

    String s = (String) m.get("key");

    如果有人已經(jīng)在映射中放置了不是 String 的其他東西,上面的代碼將會拋出 ClassCastException。泛型允許您表達(dá)這樣的類型約束,即 m 是一個將 String 鍵映射到 String 值的 Map。這可以消除代碼中的強(qiáng)制類型轉(zhuǎn)換,同時獲得一個附加的類型檢查層,這個檢查層可以防止有人將錯誤類型的鍵或值保存在集合中。

    下面的代碼示例展示了 JDK 5.0 中集合框架中的 Map 接口的定義的一部分:

    public interface Map<K, V> {

     public void put(K key, V value);

     public V get(K key);

    }

    注意該接口的兩個附加物:

    類型參數(shù) K V 在類級別的規(guī)格說明,表示在聲明一個 Map 類型的變量時指定的類型的占位符。

    get()put() 和其他方法的方法簽名中使用的 K V

    為了贏得使用泛型的好處,必須在定義或?qū)嵗?/span> Map 類型的變量時為 K V 提供具體的值。以一種相對直觀的方式做這件事:

    Map<String, String> m = new HashMap<String, String>();

    m.put("key", "blarg");

    String s = m.get("key");

    當(dāng)使用 Map 的泛型化版本時,您不再需要將 Map.get() 的結(jié)果強(qiáng)制類型轉(zhuǎn)換為 String,因為編譯器知道 get() 將返回一個 String

    在使用泛型的版本中并沒有減少鍵盤錄入;實際上,比使用強(qiáng)制類型轉(zhuǎn)換的版本需要做更多鍵入。使用泛型只是帶來了附加的類型安全。因為編譯器知道關(guān)于您將放進(jìn) Map 中的鍵和值的類型的更多信息,所以類型檢查從執(zhí)行時挪到了編譯時,這會提高可靠性并加快開發(fā)速度。

    向后兼容

    Java 語言中引入泛型的一個重要目標(biāo)就是維護(hù)向后兼容。盡管 JDK 5.0 的標(biāo)準(zhǔn)類庫中的許多類,比如集合框架,都已經(jīng)泛型化了,但是使用集合類(比如 HashMap ArrayList)的現(xiàn)有代碼將繼續(xù)不加修改地在 JDK 5.0 中工作。當(dāng)然,沒有利用泛型的現(xiàn)有代碼將不會贏得泛型的類型安全好處。


                                                                           (三)

    型參數(shù)

    在定泛型或聲明泛型,使用尖括號來指定形式型參數(shù)。形式型參數(shù)與實際類型參數(shù)之關(guān)似于形式方法參數(shù)與實際方法參數(shù)之關(guān)系,只是型參數(shù)表示型,而不是表示

    泛型中的型參數(shù)幾乎可以用于任何可以使用名的地方。例如,下面是 java.util.Map 接口的定的摘

    public interface Map<K, V> {

     public void put(K key, V value);

     public V get(K key);

    }

    Map 接口是由兩個型參數(shù)化的,兩個型是鍵類 K 值類 V。(不使用泛型)將會接受或返回 Object 的方法現(xiàn)在在它的方法名中使用 K V,指示附加的束位于 Map 規(guī)明之下。

    當(dāng)聲明或者例化一個泛型的,必指定型參數(shù)的

    Map<String, String> map = new HashMap<String, String>();

    注意,在本例中,必指定兩次型參數(shù)。一次是在聲明 map ,另一次是在選擇 HashMap 的參數(shù)化以便可以例化正確型的一個

    編譯器在遇到一個 Map<String, String> 型的,知道 K V 現(xiàn)在被 String,因此它知道在這樣量上調(diào) Map.get() 將會得到 String 型。

    除了異常型、枚或匿名內(nèi)部以外,任何都可以具有型參數(shù)。

    命名型參數(shù)

    推薦的命名定是使用大寫的個字母名稱作為類型參數(shù)。 C++ 定有所不同(參 A:與 C++ 模板的比),并反映了大多數(shù)泛型將具有少量型參數(shù)的假定。于常的泛型模式,推薦的名稱是:

    K —— ,比如映射的

    V —— ,比如 List Set 的內(nèi)容,或者 Map 中的

    E —— 異常

    T ——泛型。

    泛型不是協(xié)變

    關(guān)于泛型的混淆,一個常的來源就是假設(shè)像數(shù)協(xié)變的。其不是協(xié)變的。List<Object> 不是 List<String> 的父型。

    如果 A 擴(kuò) B,那 A 的數(shù)也是 B 的數(shù),并且完全可以在需要 B[] 的地方使用 A[]

    Integer[] intArray = new Integer[10]; 

    Number[] numberArray = intArray;

    上面的代是有效的,因一個 Integer 一個 Number,因而一個 Integer 數(shù)一個 Number 數(shù)。但是于泛型來說則不然。下面的代是無效的:

    List<Integer> intList = new ArrayList<Integer>();

    List<Number> numberList = intList; // invalid

    最初,大多數(shù) Java 程序員覺缺少協(xié)變人,或者甚至是“壞的(broken)”,但是之所以這樣有一個很好的原因。如果可以將 List<Integer> 賦給 List<Number>,下面的代就會背泛型應(yīng)該提供的型安全:

    List<Integer> intList = new ArrayList<Integer>();

    List<Number> numberList = intList; // invalid

    numberList.add(new Float(3.1415));

    intList numberList 都是有名的,如果允,上面的代就會您將不是 Integers 西放進(jìn) intList 中。但是,正如下一屏將會看到的,您有一個更加靈活的方式來定泛型。


                                                                                   (四)

    型通配符

    設(shè)您具有方法:

    void printList(List l) {

     for (Object o : l)

        System.out.println(o);

    }

    上面的代 JDK 5.0 編譯,但是如果試圖 List<Integer> 調(diào)用它,會得到警告。現(xiàn)警告是因,您將泛型(List<Integer>傳遞給一個只承將它當(dāng)作 List(所的原始型)的方法,將破壞使用泛型的型安全。

    如果試圖編寫像下面這樣的方法,那將會怎么樣

    void printList(List<Object> l) {

     for (Object o : l)

        System.out.println(o);

    }

    它仍然不會通過編譯,因一個 List<Integer> 不是一個 List<Object>(正如前一屏泛型不是協(xié)變中所學(xué)的)。才真正 —— 現(xiàn)在您的泛型版本沒有普通的非泛型版本有用!

    解決方案是使用型通配符:

    void printList(List<?> l) {

     for (Object o : l)

        System.out.println(o);

    }

    上面代中的號是一個型通配符。它作“號”。List<?> 是任何泛型 List 的父型,所以您完全可以將 List<Object>List<Integer> List<List<List<Flutzpah>>> 傳遞給 printList()

    型通配符的作用

    型通配符中引入了型通配符,這讓您可以聲明 List<?> 型的量。您可以對這樣 List 做什呢?非常方便,可以從中索元素,但是不能添加元素。原因不是編譯器知道哪些方法修改列表哪些方法不修改列表,而是(大多數(shù))化的方法比不化的方法需要更多的型信息。下面的代碼則工作得很好:

    List<Integer> li = new ArrayList<Integer>();

    li.add(new Integer(42));

    List<?> lu = li;

    System.out.println(lu.get(0));

    么該能工作呢? lu編譯器一點都不知道 List 型參數(shù)的。但是編譯器比較聰明,它可以做一些型推理。在本例中,它推斷未知的型參數(shù)必須擴(kuò) Object。(個特定的推理沒有太大的跳,但是編譯器可以作出一些非常令人佩服的型推理,后面就會看到(在層細(xì)節(jié)節(jié)中)。所以它調(diào) List.get() 并推斷返回 Object

    另一方面,下面的代不能工作:

    List<Integer> li = new ArrayList<Integer>();

    li.add(new Integer(42));

    List<?> lu = li;

    lu.add(new Integer(43)); // error

    在本例中, lu編譯器不能 List 型參數(shù)作出足夠嚴(yán)密的推理,以確定將 Integer 傳遞給 List.add() 型安全的。所以編譯器將不允這么做。

    以免您仍然認(rèn)為編譯器知道哪些方法更改列表的內(nèi)容哪些不更改列表內(nèi)容,注意下面的代將能工作,因它不依編譯器必知道關(guān) lu 型參數(shù)的任何信息:

    List<Integer> li = new ArrayList<Integer>();

    li.add(new Integer(42));

    List<?> lu = li;

    lu.clear();

    泛型方法 

    (在型參數(shù)節(jié)中)您已經(jīng)看到,通的定中添加一個形式型參數(shù)列表,可以將泛型化。方法也可以被泛型化,不管它在其中的是不是泛型化的。

    泛型在多個方法間實束。在 List<V> 中,型參數(shù) V 現(xiàn) get()add()contains() 等方法的名中。當(dāng)創(chuàng)建一個 Map<K, V> 型的,您就在方法之宣稱一個束。您傳遞給 add() 將與 get() 返回的型相同。

    似地,之所以聲明泛型方法,一般是因您想要在方法的多個參數(shù)之宣稱一個。例如,下面代中的 ifThenElse() 方法,根據(jù)它的第一個參數(shù)的布爾值,它將返回第二個或第三個參數(shù):

    public <T> T ifThenElse(boolean b, T first, T second) {

     return b ? first : second;

    }

    注意,您可以調(diào) ifThenElse(),而不用式地告訴編譯器,您想要 T 的什么值編譯器不必式地被告知 T 將具有什么值;它只知道都必相同。編譯器允調(diào)用下面的代,因為編譯器可以使用型推理來推斷出,替 T String 滿足所有的束:

    String s = ifThenElse(b, "a", "b");

    似地,您可以調(diào)用:

    Integer i = ifThenElse(b, new Integer(1), new Integer(2));

    但是,編譯器不允下面的代,因沒有型會滿足所需的束:

    String s = ifThenElse(b, "pi", new Float(3.14));

    選擇使用泛型方法,而不是將 T 添加到呢?(至少)有兩情況應(yīng)該這樣做:

    當(dāng)泛型方法是靜態(tài)這種情況下不能使用類類型參數(shù)。

    當(dāng) T 上的于方法真正是局部的意味著沒有在相同的另一個方法名中使用相同 T 束。通使得泛型方法的型參數(shù)于方法是局部的,可以化封閉類型的名。

    有限制

    在前面泛型方法的例子中,型參數(shù) V 是無束的或無限制的型。有沒有完全指定型參數(shù),需要對類型參數(shù)指定附加的束。

    例子 Matrix ,它使用型參數(shù) V參數(shù)由 Number 來限制:

    public class Matrix<V extends Number> { ... }

    編譯器允創(chuàng) Matrix<Integer> Matrix<Float> 型的量,但是如果您試圖 Matrix<String> 型的量,會出現(xiàn)錯誤型參數(shù) V 被判斷 Number 限制在沒有型限制,假設(shè)類型參數(shù)由 Object 限制。就是前一屏泛型方法中的例子,允 List.get() List<?> 調(diào)返回 Object,即使編譯器不知道型參數(shù) V
    posted on 2008-10-24 09:35 蘆葦 閱讀(506) 評論(0)  編輯  收藏 所屬分類: JAVA
    主站蜘蛛池模板: 18gay台湾男同亚洲男同| 亚洲国产一成人久久精品| 国产精品亚洲综合久久| 久久精品国产免费观看三人同眠| 亚洲色中文字幕无码AV| 国产色无码精品视频免费| 久久青草亚洲AV无码麻豆| 特级精品毛片免费观看| 亚洲酒色1314狠狠做| 国产成人免费高清激情明星| 亚洲一区二区三区免费在线观看 | 亚洲中文字幕无码av在线| 黄页网站免费在线观看| 亚洲欧洲日韩国产一区二区三区| 无码国产精品久久一区免费| 亚洲码和欧洲码一码二码三码| 狠狠久久永久免费观看| 人成电影网在线观看免费| 亚洲综合亚洲综合网成人| 日韩av无码免费播放| 亚洲精品成人网站在线播放| 国产va免费精品观看精品| 黑人粗长大战亚洲女2021国产精品成人免费视频 | 99精品视频在线观看免费| 亚洲高清在线播放| 无码人妻久久一区二区三区免费丨 | 亚洲国产成人久久精品99| 手机看片国产免费永久| 亚洲六月丁香六月婷婷蜜芽| 国语成本人片免费av无码| 一边摸一边爽一边叫床免费视频| 亚洲国产精品一区二区成人片国内| 一区二区三区在线免费看| 97久久国产亚洲精品超碰热| 成人亚洲综合天堂| 91精品导航在线网址免费| 亚洲成a人片在线观看天堂无码| 国产日韩成人亚洲丁香婷婷| 亚洲人成免费网站| 色婷婷综合缴情综免费观看| 亚洲日本中文字幕区|