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

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

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

    空間站

    北極心空

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks

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

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

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

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

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

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

    是泛型?

    泛型(Generic type 或者 generics)是 Java 言的型系的一種擴展,以支持建可以按行參數化的??梢园?/span>型參數看作是使用參數指定的型的一個占位符,就像方法的形式參數是運行時傳遞的占位符一

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

    Map.get() 被定義為返回 Object,所以一般必 Map.get() 轉換為期望的型,如下面的代所示:

    Map m = new HashMap();

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

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

    程序通過編譯,必 get() 轉換為 String,并且希望果真的是一個 String。但是有可能某人已映射中保存了不是 String 西,這樣,上面的代將會拋出 ClassCastException。

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

    泛型的好

    Java 言中引入泛型是一個大的功能增。不僅語言、型系編譯器有了大的化,以支持泛型,而且類庫行了大翻修,所以多重要的,比如集合框架,都已泛型化的了。這帶來了很多好

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

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

    消除轉換泛型的一個附是,消除源代中的轉換。使得代更加可,并且減少了出機會。

    盡管減少轉換可以降低使用泛型的代羅嗦程度,但是聲明泛型量會來相羅嗦。比下面兩個代例子。

    不使用泛型:

    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);

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

    潛在的性能收益。泛型為較大的來可能。在泛型的初始實現中,編譯器將轉換(沒有泛型的,程序會指定轉換)插入生成的字節碼中。但是更多型信息可用于編譯未來版本的 JVM 來可能。

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


                                                                               (二)

    泛型用法的例子

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

    Map m = new HashMap();

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

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

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

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

    public interface Map<K, V> {

     public void put(K key, V value);

     public V get(K key);

    }

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

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

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

    為了贏得使用泛型的好處,必須在定義或實例化 Map 類型的變量時為 K V 提供具體的值。以一種相對直觀的方式做這件事:

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

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

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

    當使用 Map 的泛型化版本時,您不再需要將 Map.get() 的結果強制類型轉換為 String,因為編譯器知道 get() 將返回一個 String。

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

    向后兼容

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


                                                                           (三)

    型參數

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

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

    public interface Map<K, V> {

     public void put(K key, V value);

     public V get(K key);

    }

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

    當聲明或者例化一個泛型的,必指定型參數的

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

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

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

    除了異常型、枚或匿名內部以外,任何都可以具有型參數。

    命名型參數

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

    K —— ,比如映射的。

    V —— ,比如 List Set 的內容,或者 Map 中的。

    E —— 異常。

    T ——泛型。

    泛型不是協變

    于泛型的混淆,一個常的來源就是假像數協變的。其不是協變的。List<Object> 不是 List<String> 的父型。

    如果 A B,那 A 的數也是 B 的數,并且完全可以在需要 B[] 的地方使用 A[]

    Integer[] intArray = new Integer[10]; 

    Number[] numberArray = intArray;

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

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

    List<Number> numberList = intList; // invalid

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

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

    List<Number> numberList = intList; // invalid

    numberList.add(new Float(3.1415));

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


                                                                                   (四)

    型通配符

    您具有方法:

    void printList(List l) {

     for (Object o : l)

        System.out.println(o);

    }

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

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

    void printList(List<Object> l) {

     for (Object o : l)

        System.out.println(o);

    }

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

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

    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 做什呢?非常方便,可以從中索元素,但是不能添加元素。原因不是編譯器知道哪些方法修改列表哪些方法不修改列表,而是(大多數)化的方法比不化的方法需要更多的型信息。下面的代碼則工作得很好:

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

    li.add(new Integer(42));

    List<?> lu = li;

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

    么該能工作呢? lu,編譯器一點都不知道 List 型參數的。但是編譯器比較聰明,它可以做一些型推理。在本例中,它推斷未知的型參數必須擴 Object。(個特定的推理沒有太大的跳,但是編譯器可以作出一些非常令人佩服的型推理,后面就會看到(在層細節中)。所以它調 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 型參數作出足夠嚴密的推理,以確定將 Integer 傳遞給 List.add() 型安全的。所以編譯器將不允這么做。

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

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

    li.add(new Integer(42));

    List<?> lu = li;

    lu.clear();

    泛型方法 

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

    泛型在多個方法間實束。在 List<V> 中,型參數 V get()、add()、contains() 等方法的名中。當建一個 Map<K, V> 型的,您就在方法之宣稱一個束。您傳遞給 add() 將與 get() 返回的型相同。

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

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

     return b ? first : second;

    }

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

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

    似地,您可以調用:

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

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

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

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

    當泛型方法是靜,這種情況下不能使用類類型參數。

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

    有限制

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

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

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

    編譯器允 Matrix<Integer> Matrix<Float> 型的量,但是如果您試圖 Matrix<String> 型的量,會出現錯誤。型參數 V 被判斷 Number 限制。在沒有型限制,假設類型參數由 Object 限制。就是前一屏泛型方法中的例子,允 List.get() List<?> 調返回 Object,即使編譯器不知道型參數 V
    posted on 2008-10-24 09:35 蘆葦 閱讀(506) 評論(0)  編輯  收藏 所屬分類: JAVA
    主站蜘蛛池模板: 男人的天堂亚洲一区二区三区| 亚洲国产高清美女在线观看| aa级一级天堂片免费观看| 一区二区三区在线免费| 在线观看亚洲AV日韩A∨| 亚洲免费视频播放| a在线视频免费观看| 老司机亚洲精品影院在线观看| 久久精品国产亚洲AV无码娇色| 亚洲午夜精品一级在线播放放| 日本一区免费电影| 国产一卡二卡四卡免费| 91免费福利视频| 一边摸一边桶一边脱免费视频| 亚洲国产精品无码久久久秋霞1| 亚洲嫩草影院在线观看| 亚洲天堂男人天堂| 亚洲第一AV网站| 最新国产AV无码专区亚洲| 亚洲AV伊人久久青青草原| 日本免费v片一二三区| 男人的好免费观看在线视频| 中文字幕成人免费视频| 久99久精品免费视频热77| 老司机69精品成免费视频| 国产免费久久久久久无码| 日韩一级片免费观看| 色多多A级毛片免费看| 黄色毛片免费在线观看| 精品在线视频免费| 精品国产日韩亚洲一区91| 亚洲欧美日韩久久精品| h视频在线免费观看| 成人精品国产亚洲欧洲| 久久亚洲欧美国产精品| 亚洲欧美日韩国产精品一区| 国产午夜亚洲精品不卡| 最好2018中文免费视频| h视频在线观看免费| 成人爽a毛片免费| 99在线观看免费视频|