Java泛型

1 什么是泛型


泛型即參數化類型,即是將類型由原本的類型參數化,類似于方法中的變量參數,此時類型也可以當作參數傳入(可以稱之為類型參數)。

2 為什么要使用泛型


先看一段代碼:

List list = new ArrayList();  
list.add("Acey");  
list.add(100);  
for (int i = 0; i < list.size(); i++) {  
  String name = (String) list.get(i); //取出Integer時,運行時出現異常  
System.out.println("name:" + name);  
} 

當我們在list中插入一個字符串和整數時是合法的,因為list默認的泛型即為Object類型。但是當我們從集合中取出數據時,需要對不同的類型進行強轉成符合的對應的類型。為了解決這一問題,泛型就出現了。

3 泛型的使用


  • Java泛型變成時在jdk1.5版本后引出的,使用的時候注意了。。
  • 泛型只在編譯階段有用,在編譯的過程中,將會正確的檢驗泛型的結果,將泛型的相關信息擦除,在對象進入和離開方法的邊界時會加上對應的類型轉換方法。也就是說在成功編譯成class文件后將不會在包含任何泛型的信息。

4 泛型方法


對于常見的泛型模式,推薦的名稱:
K - 鍵
V - 值
E - 異常
T - 泛型

泛型方法使得該方法能獨立于類而產生變化。以下是一個基本的指導原則:無論何時,只要你能做到,你就應該盡量使用泛型方法。也就是說,如果使用泛型方法可以取代將整個類泛型化,那么就應該只使用泛型方法,因為它可以使事情更清楚明白。另外,對于一個static的方法而言,無法訪問泛型類的類型參數。所以,如果static方法需要使用泛型能力,就必須使其成為泛型方法。
要定義泛型方法,只需將泛型參數列表置于返回值之前,就像下面這樣:

 public <T> void f(T x){  
        System.out.println(x.getClass().getName());  
    }  

可變參數與泛型方法
public static <T> List<T> makeList(T... args){  
        List<T> result = new ArrayList<T>();  
        for(T item:args)  
            result.add(item);  
        return result;         
    }  

5 構建一個復雜的元組


元組和``list```列表一樣,都是用來存儲數據,但是和列表不同的是,列表只能存儲相同的數據類型,而元組可以存儲多種數據類型,且可以根據自己的需求無線擴展。

class ThreeTuple2<A,B,C>{  
    public final A first;  
    public final B second;  
    private final C three;  
    public ThreeTuple2(A a,B b,C c){  
        first = a;  
        second = b;  
        three = c;  
    }  
    public String toString(){  
        return "(" + first + "," + second + "," + three + ")";  
    }  
} 

6 泛型通配符 “ ? ”


在不確定使用哪種類型的時候可以使用泛型通配符 “? ”來代替,但是在操作該類型的對象時,只能使用Object中的功能。

Class<?>classType = Class.forName("java.lang.String");

7 泛型的上限和下限


上限:? extends E 可以接收 E 類型或E類型以下的類型對象
上限:? super E 可以接收E類型或E類型以上的類型對象。

7 泛型擦除

java 泛型是用泛型擦除來實現的,類型擦除就是說Java泛型只能用于在編譯期間的靜態類型檢查,然后編譯器生成的代碼會擦除相應的類型信息,這樣到了運行期間實際上JVM根本就知道泛型所代表的具體類型。這樣做的目的是因為Java泛型是1.5之后才被引入的,為了保持向下的兼容性,所以只能做類型擦除來兼容以前的非泛型代碼

public class Node<T> {
    private T data;
    private Node<T> next;
    public Node(T data, Node<T> next) {
        this.data = data;
        this.next = next;
    }
    public T getData() { return data; }

}

編譯器在做了相應的檢查后,在運行期間上面的代碼會轉換為

public class Node {
    private Object data;
    private Node next;
    public Node(Object data, Node next) {
        this.data = data;
        this.next = next;
    }
    public Object getData() { return data; }
    // ...
}

這也就是說,我們若只是給定了泛型參數 T 的話,那么不管我們傳進來的是 Integer 還是 String .... 最終都會被當作 Object 來看待。
如果我們想要設置自己的 bounds ,那么我們就應該使用上限來設置。

public class Node<T extends Comparable<T>> {
    private T data;
    private Node<T> next;
    public Node(T data, Node<T> next) {
        this.data = data;
        this.next = next;
    }
    public T getData() { return data; }
    // ...
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 開發人員在使用泛型的時候,很容易根據自己的直覺而犯一些錯誤。比如一個方法如果接收List作為形式參數,那么如果嘗試...
    時待吾閱讀 1,072評論 0 3
  • 我們知道,使用變量之前要定義,定義一個變量時必須要指明它的數據類型,什么樣的數據類型賦給什么樣的值。 假如我們現在...
    今晚打肉山閱讀 1,000評論 0 1
  • 一、泛型簡介1.引入泛型的目的 了解引入泛型的動機,就先從語法糖開始了解。 語法糖 語法糖(Syntactic S...
    Android進階與總結閱讀 1,031評論 0 9
  • 安裝node.js 和npm https://nodejs.org/en/ 或者官網下載: 安裝watchman:...
    perfect_jimmy閱讀 1,042評論 0 0
  • 12.10我們走進了北京師范大學,再次聆聽全國特級教師,大同名師培養工程總顧問吳瓊老師的講座! 聚焦課堂做研究:關...
    moneydmn閱讀 1,208評論 0 0