JDK5.0新特性的學習--泛型(上)
沒有泛型的日子
所有的java類都源自java.lang.Object,這意味著所有的JAVA物件能轉換成Object。因此,在之前的JDK的版本中,很多集合框架的函式接受一個Object引數。所以,collections是一個能持有任何物件的多用途工具,但帶來了不良的後果。
舉個簡單的例子,在JDK 5.0的之前版本中,類List的函式add接受一個Object引數:
- public boolean add(java.lang.Object element)
所以你能傳遞任何型別給add。這是故意這麼設計的。否則,它只能傳遞某種特定的物件,這樣就會出現各種List型別,如,StringList, EmployeeList, AddressList等。
add透過Object傳遞能帶來好處,現在我們考慮get函式(返回List中的一個元素).如下是JDK 5之前版本的定義:
- public java.lang.Object get(int index) throws IndexOutOfBoundsException
get返回一個Object.不幸的事情從此開始了.假如你儲存了兩個String物件在一個List中:
- List stringList1 = new ArrayList();
- stringList1.add("Java 5");
- stringList1.add("with generics");
當你想從stringList1取得一個元素時,你得到了一個Object.為了操作原來的型別元素,你不得不把它轉換為String。
- String s1 = (String) stringList1.get(0);
但是,假如你曾經把一個非String物件加入stringList1中,上面的程式碼會丟擲一個ClassCastException. 有了泛型,你能建立一個單一用途的List例項.比如,你能建立一個只接受String物件的List例項,另外一個例項只能接受Employee物件.這同樣適用於集合框架中的其他型別.
泛型入門
像一個函式能接受引數一樣,一個泛型也能接受引數.這就是一個泛型經常被稱為一個引數化型別的原因.但是不像函式用()傳遞引數,泛型是用<>傳遞引數的.宣告一個泛型和宣告一個普通類沒有什麼區別,只不過你把泛型的變數放在<>中.
比如,在JDK 5中,你可以這樣宣告一個java.util.List : List
E 稱為型別變數.意味著一個變數將被一個型別替代.替代型別變數的值將被當作引數或返回型別.對於List介面來說,當一個例項被建立以後,E 將被當作一個add或別的函式的引數.E 也會使get或別的引數的返回值.下面是add和get的定義:
- boolean add E get(int index)
一個泛型在宣告或例示時允許你傳遞特定的型別變數: E.除此之外,如果E是個類,你可以傳遞子類;如果E是個介面,你可以傳遞實現介面的類;
- List numberList= new ArrayList();
- numberList.add(2.0);
- numberList.add(2);
-----------------------------譯者新增--------------------
那麼mylist的add函式將接受一個String作為他的引數,而get函式將返回一個String.因為返回了一個特定的型別,所以不用型別轉化了。
根據慣例,我們使用一個唯一的大寫字目表示一個型別變數。為了建立一個泛型,你需在宣告時傳遞同樣的引數列表。比如,你要想建立一個ArrayList來操作String ,你必須把String放在<>中。如:
- List myList = new ArrayList();
再比如,java.util.Map 是這麼定義的:
public interface Map
K用來宣告map鍵(KEY)的型別而V用來表示值(VALUE)的型別。put和values是這麼定義的:
V put(K key, V value)
Collection
一個泛型不準直接的或間接的是java.lang.Throwable的子類。因為異常是在執行時丟擲的,所以它不可能預言什麼型別的異常將在編譯時丟擲.
列表1的例子將比較List在JDK 1.4 和JDK1.5的不同
- public class GenericListTest {
- public static void main(String[] args) {
- // in JDK 1.4
- List stringList1 = new ArrayList();
- stringList1.add("Java 1.0 - 5.0");
- stringList1.add("without generics");
- // cast to java.lang.String
- String s1 = (String) stringList1.get(0);
- System.out.println(s1.toUpperCase());
- // now with generics in JDK 5
- List stringList2 = new ArrayList();
- stringList2.add("Java 5.0");
- stringList2.add("with generics");
- // no need for type casting
- String s2 = stringList2.get(0);
- System.out.println(s2.toUpperCase());
- }
- }
在列表1中,stringList2是個泛型。宣告List
泛型的型別檢查(type checking)是在編譯時完成的.
最讓人感興趣的事情是,一個泛型是個型別並且能被當作一個型別變數。比如,你想你的List儲存lists of Strings,你能透過把List
- List
> myListOfListsOfStrings;
要從myList中的第一個List重新取得String,你可以這麼用:
- String s = myListOfListsOfStrings.get(0).get(0);
下一個列表中的ListOfListsTest類示範了一個List(命名為listOfLists)接受一個String List作為引數。
- public class ListOfListsTest {
- public static void main(String[] args) {
- List listOfStrings = new ArrayList();
- listOfStrings.add("Hello again");
- List> listOfLists = new ArrayList>();
- listOfLists.add(listOfStrings);
- String s = listOfLists.get(0).get(0);
- System.out.println(s); // prints "Hello again"
- }
- }
另外,一個泛型接受一個或多個型別變數。比如,java.util.Map有兩個型別變數s。第一個定義了鍵(key)的型別,第二個定義了值(value)的型別。下面的例子講教我們如何使用個一個泛型Map.
- public class MapTest {
- public static void main(String[] args) {
- Map map = new HashMap();
- map.put("key1", "value1");
- map.put("key2", "value2");
- String value1 = map.get("key1");
- }
- }
在這個例子中,重新得到一個key1代表的String值,我們不需要任何型別轉換。
-----------------------------譯者新增--------------------
如果你傳遞一個String給一個List,比如:
List
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/800861/viewspace-922111/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 學習Rust泛型與特性Rust泛型
- Rust 泛型與特性Rust泛型
- C#泛型學習C#泛型
- 泛型學習筆記泛型筆記
- Java JDK1.5: 泛型 新特性的講解說明JavaJDK泛型
- Java高階特性—泛型Java泛型
- 第 80 期帶你提前玩 Go 2 新特性:泛型Go泛型
- TypeScript學習(四)—— 介面和泛型TypeScript泛型
- rust學習十一.1、泛型(通用型別)Rust泛型型別
- C#學習 [型別系統] 泛型(16)C#型別泛型
- java入門基礎學習----泛型Java泛型
- JDK 1.8 新特性學習(Stream)JDK
- Java1.8新特性學習Java
- Go型別特性-學習筆記Go型別筆記
- iOS學習筆記47 Swift(七)泛型iOS筆記Swift泛型
- 深圳大資料學習:泛型--【千鋒】大資料泛型
- Java泛型複習Java泛型
- Automatic Reference Counting(ARC)特性學習(iOS5新特性學習之五)iOS
- JDK11新特性學習(二)JDK
- JDK11新特性學習(一)JDK
- C++ 11 新特性 nullptr 學習C++Null
- 學習 Java,你不得不知的泛型知識Java泛型
- 泛型--泛型萬用字元和泛型的上下限泛型字元
- Java進階學習之集合與泛型(1)Java泛型
- JDK8 新特性學習筆記JDK筆記
- jdk-1.8新特性學習筆記JDK筆記
- JDK8新特性學習總結JDK
- swift4.1 系統學習二十一 泛型Swift泛型
- 泛型類、泛型方法及泛型應用泛型
- 【java】【泛型】泛型geneticJava泛型
- 2019 年的 JavaScript 新特性學習指南 | 掘金年度徵文JavaScript
- java基礎複習-----泛型Java泛型
- 學習筆記~1.4 HTML5新特性筆記HTML
- 一起學習React18 新特性React
- 重學Java之泛型的基本使用Java泛型
- 泛型類和泛型方法泛型
- HTML5的新特性概述(上)HTML
- 泛型類、泛型方法、型別萬用字元的使用泛型型別字元
- 學習七、ES2016與ES2017的新特性