首頁 > 軟體

Java 泛型超詳細入門講解

2022-04-02 19:01:20

1、什麼是泛型?

泛型其實就是將型別作為引數傳遞,泛型允許程式設計師在編寫程式碼時使用一些以後才指定的型別 ,在範例化該類時將想要的型別作為引數傳遞,來指明這些型別。

為什麼要引入泛型?

例如:自己實現一個順序表

public class MyArrayList {
    public int[] elem;
    public int usedSize;

    public MyArrayList() {
        this.elem = new int[10];
    }
    // add方法
    public void add(int val) {
        // 暫時不考慮擴容問題,這裡只是為了講泛型
        elem[usedSize++] = val;
    }
    // get方法
    public int get(int pos) {
        return elem[pos];
    }
}

這裡可以看出,在使用上面這個自定義的順序表時,我們只能新增 int 型別的元素,我們知道java集合中的順序表,可以新增任何型別的資料,怎麼實現的呢?這裡我們先嚐試將 int 型別變為Object型別,這樣就可以保證能傳入任何型別。

public class MyArrayList {
    public Object[] elem;
    public int usedSize;

    public MyArrayList() {
        this.elem = new Object[10];
    }
    // add方法
    public void add(Object val) {
        // 暫時不考慮擴容問題,這裡只是為了講泛型
        elem[usedSize++] = val;
    }
    // get方法
    public Object get(int pos) {
        return elem[pos];
    }
}

main方法中往物件中新增資料時,可以新增任意型別的資料。但是,當需要取出資料時,因為返回的是Object型別,需要進行強轉才能用相對應的型別來接收,非常麻煩。

public static void main(String[] args) {
        MyArrayList myArrayList = new MyArrayList();
        myArrayList.add(1);
        myArrayList.add("hello");
        int array1 = (int)myArrayList.get(0);
        String array2 = (String)myArrayList.get(1);
    }

所以問題來了,難道每次都要強轉一下才能接收嗎,能否不強轉呢?這時候我們就想到在建立一個範例物件時,可以將想要的型別作為引數傳遞,讓這個物件中全部存傳入的型別的資料,那麼拿出來的時候,就可以明確該物件中所有的資料都是該型別,不需要強轉了。這就引入了泛型。

public class MyArrayList<E> {
	// 在編寫程式時,不指定具體的型別,而用<E>這裡的E來暫時代替
    // 具體的型別在範例化物件時傳入
    public E[] elem;
    public int usedSize;

    public MyArrayList() {
    	// 這裡的寫法不是特別準確,應該用反射機制,這裡先這樣寫
        this.elem = (E[])new Object[10];
    }
    // add方法
    public void add(E val) {
        // 暫時不考慮擴容問題,這裡只是為了講泛型
        elem[usedSize++] = val;
    }
    // get方法
    public E get(int pos) {
        return elem[pos];
    }
}
public static void main(String[] args) {

        MyArrayList<Integer> myArrayList1 = new MyArrayList<>();
        myArrayList1.add(1);
        myArrayList1.add(3);
        // myArrayList1.add("world");// 這裡會報錯,因為傳入的資料不是指定的型別,所以泛型還有自動對型別進行檢查的作用
        int I1 = myArrayList1.get(0);
        
        MyArrayList<String> myArrayList2 = new MyArrayList<>();
        myArrayList2.add("hello");
        myArrayList2.add("world");
        String s1 = myArrayList2.get(0);
    }

這樣就保證了能傳入任何型別的資料,同時在拿出時也不需要強轉!

泛型的意義:

1、自動對型別進行檢查

2、自動對型別進行強制型別轉換

那麼這裡MyArrayList對應物件的型別是什麼呢?是MyArrayList< Integer > 之類的嗎?

這裡可以看出,範例建立的物件他的型別都是MyArrayList,而<>中的內容不參與泛型型別的組成,那麼<>裡面的型別哪裡去了呢?這就要了解泛型的工作機制了。

2、泛型是怎麼編譯的

陣列和泛型之間的一個重要區別是它們如何強制型別檢查。具體來說,陣列在執行時儲存和檢查型別資訊。但是,泛型在編譯時檢查型別錯誤,並且在執行時沒有型別資訊。

泛型的編譯機制:擦除機制

在編譯時,將 MyArrayList 中的 E 擦成了 Object 型別。

在main方法中都擦成了 MyArrayList 型別。

參考: 在java中建立泛型陣列

到此這篇關於Java 泛型超詳細入門講解的文章就介紹到這了,更多相關Java 泛型內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com