泛型瑣碎之泛型方法

泛型

泛型:是一種把類型明確的工作推遲到創建對象或者調用方法的時候才去明確的特殊的類型。把類型當作參數傳遞。

格式:<數據類型> 此處的數據類型只能是引用類型, 如<E>, 丟進去的類型必須是E的對象或其子類的對象。

好處:
A:把運行時期的問題提前到了編譯期間
B:避免了強制類型轉換
C:優化了程序設計,解決了黃色警告線

泛型方法

such as, ResponseEntity類帶有一個E類型形參

public class ResponseEntity<E> {
    private String msg;
    private String code; 
    private E data;
    
    public ResponseEntity(String code, String msg, E data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
    
    /*
    方法靜態時,不能訪問類定義上的泛型
    */
    public static <E> ResponseEntity<E> success(String code, String msg, E data) {
    // 傳入什么類型,E就是什么類型 
        return new ResponseEntity<E>(code, msg, data);
    }
} 

現在假設有一個

Apple a = new Apple();
// 調用success()方法, 
ResponseEntity.success("200", "ok", a);
//這樣success()方法的返回值類型 ResponseEntity<E>中的E代表Apple類型。

再比如:

public static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
    for (T o : a) {
        c.add(o);
    }
}

這是一個泛型方法,該泛型方法定義一個T類型形參,這樣方法就能接受任意類型的參數了。

Integer[] ia = new Integer[100];
Collection<Number>  cn = new ArrayList<>();
// T代表Number類型
// 只比較泛型形參: Collection<T> cn
fromArrayToCollection(ia, cn);

cn是Collection<Number>類型,與此方法的方法簽名進行比較——只比較泛型參數,故該T類型形參代表了Number類型。

public static <T> void test(Collection<? extends T> from, Collection<T> to) {
    for (T ele : from) {
        to.add(ele);
    }
}

//String Object
List<Object> ao = new ArrayList<>();
List<String> as = new ArrayList<>();
// T代表Object類型, as中的String是Object的子類類型
test(as, ao);

泛型方法和類型通配符(?)

大多時候,可以使用泛型方法來代替類型通配符。如Java的Collection接口中的兩個方法:

// 泛型通配符
public interface Collection<E> {
    boolean containsAll(Collection<?> c);
    boolean addAll(Collection<? extends E> c);
}

//采用泛型方法的形式
public interface Collection<E> {
    <T> boolean containsAll(Collection<T> c);
    <T extends E> boolean addAll(Collection<T> c);
}

上面兩個方法中類型形參T只使用了一次,類型形參T產生的唯一效果是可以在不同的調用點傳入不同的實際類型。對于這種情況,應該使用通配符:通配符就是被設計用來支持靈活的子類化的

泛型方法允許類型形參被用來表示方法的一個或多個參數之間的類型依賴關系,或者方法返回值與參數之間的類型依賴關系。如果沒有這種依賴關系,就不應該使用泛型方法。

再來看一個栗子, Collections.copy()方法:

public class Collections {
    public static <T> void copy(List<T> dest, List<? extends T> src){...}
}
/*
src中 ? 代表的類型須是dest中 T 的子類或它本身
dest于src的類型存在明顯的依賴關系
但JDK定義src時使用的是類型通配符,而不是泛型方法
Reason: 該方法無須向src集合中添加元素,也無須修改src集合里的元素,使用類型通配符,無須使用泛型方法
*/

如果改成泛型方法,不使用類型通配符:

class Collections {
    public static <T, S extends T> void copy(List<T> dest, 
    List<S> src) {...}
}
/*
這里的類型形參S, 它使用了一次, 其他參數的類型、方法返回值的類型都不依賴于它,
那類型形參S就沒有存在的必要,即可以用通配符來代替S。so Java 設計該方法時采用了通配符,而不是泛型方法。
*/

類型通配符既可以在方法簽名中定義形參的類型,也可以用于定義變量的類型;但泛型方法中的類型形參必須在對應方法中顯式聲明。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • object 變量可指向任何類的實例,這讓你能夠創建可對任何數據類型進程處理的類。然而,這種方法存在幾個嚴重的問題...
    CarlDonitz閱讀 935評論 0 5
  • 開發人員在使用泛型的時候,很容易根據自己的直覺而犯一些錯誤。比如一個方法如果接收List作為形式參數,那么如果嘗試...
    時待吾閱讀 1,073評論 0 3
  • 一、泛型簡介1.引入泛型的目的 了解引入泛型的動機,就先從語法糖開始了解。 語法糖 語法糖(Syntactic S...
    Android進階與總結閱讀 1,033評論 0 9
  • 一、泛型的概念 泛型就是:類型參數化,處理的數據類型不是固定的,而是可以作為參數傳入;瘋狂講義定義:泛型就是允許在...
    Serenity那年閱讀 722評論 2 0
  • 我以前不是這樣的 一首歌我最多聽五十次 我就膩到連前奏響起我都特別厭惡 我以前不是這樣的 我對一個人的好感不超過三...
    EPARGNer閱讀 240評論 1 0