理解Java泛型 通配符 ? 以及其使用


什么是泛型:

泛型從字面上理解,是指一個類、接口或方法支持多種類型,使之廣泛化、一般化和更加通用。Java中使用Object類來定義類型也 能實現泛型,但缺點是造成原類型信息的丟失,在使用中容易造成ClassCastException。

Java泛型帶到的好處:

  1. 使得一個類或方法中的類型參數化,最終達到代碼復用的效果。( 不使用泛型,你可能需要每種情況的類或方法都要定義一遍 )
  2. 實現類型檢查的功能,避免ClassCastException。(這是相對於使用Object類型實現泛型而言。因為我可以每個類都定義一遍來實現所謂的類型檢查。)

泛型自定義:類、接口、方法

//定義泛型類,接口的定義和類一樣
class G1<T> {
    T content;
}

// 定義泛型方法,方法的頭部使用<T>聲明,注意結構
class GMethod1 {

    // 一般泛型方法定義
    public static <T> void method1(T params) {

    }

    // 返回值也為泛型
    public static <E> E method2(E params) {
        E content = params;
        return content;
    }

}

// extends 的使用,限定泛型的范圍,等於或者是extends的子類;只有extends,沒有super,通配符才有extends和super
class G2<T extends Number> {
    T content;
}

 

泛型的使用

    //泛型類或接口的使用
    List<String> list = new ArrayList<>();

    //泛型方法的使用,在方法前面使用<>傳入類型
    <String>gMethod1.method1("str");
    <Integer>gMethod1.method1(new Integer(1));

    //如果入參的參數中使用了T,則可以省略方法前面的<>,編譯器可以自行識別出其類型
    gMethod1.method1("str");
    gMethod1.method1(new Integer(1));

 

通配符?

什么時候會用通配符:

通配符只有在修飾一個變量時會用到,使用它可方便地引用包含了多種類型的泛型;

    public static void main() {

        //不使用通配符
        ArrayList<Object> arr = new ArrayList<Object>();
        // ArrayList<Object> arr = new ArrayList<String>(); 編譯不通過,arr只能引用包含Object的集合

        //使用通配符
        ArrayList<?> arr2;
        arr2 = new ArrayList<String>();
        arr2 = new ArrayList<Integer>();
        arr2.get(0);    //返回的,是一個Object對象,通配符會使原集合包含類型信息丟失,也是通配符的使用代價 // 通常在方法參數中才會使用通配符,使得這個方法可以引用多種泛型集合。這個和范型方法不一樣,這里只是一個引用變量
    void gMethod(ArrayList<? extends Number> param) {
    }

 

可以看到,通配符使用方便的同時,使原集合包含類型信息丟失。

通配符的extends super關鍵字

詳解:https://blog.csdn.net/qq_35923521/article/details/77717308

        ArrayList<? extends Number> arr3; // Number 是 Integer、Float的父類; ArrayList<Number> arr3只能引用 ArrayList<Number>
        arr3 = new ArrayList<Integer>();
        arr3 = new ArrayList<Float>();
        // arr3 = new ArrayList<String>(); 編譯不通過,String 和 Number不存在繼承關系

        arr3.get(0);    //返回的,是一個Number對象
        arr3.add(null); //使用過通配符修飾的集合變量,只能add(null),因為這個集合中包含的類型已經確定,只是類型信息已經丟失了,add(Object)也不行

 

無限定通配符?

ArrayList<?> arr3;  無通配符等同於 ArrayList<? extends Object> arr3;   //用於取值get(),不能賦值set()

 

擴展:不使用泛型的變量和另一種方式

        //這樣使用功能和通配符一樣,可以多種引用,但一般不推薦這樣使用
        ArrayList a4;
        a4 = new ArrayList<String>();
        a4 = new ArrayList<Integer>();
        a4.add(new Integer(1));
        a4.add(new String("str"));//和通配符引用不能add不一樣,這樣方式可以add多種類型元素,但一般不推薦

        a4.get(0);  //返回的,是一個Object對象

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM