是你眼中的泛型嗎?

《? extends T與? super T》以後,咱們再聊聊泛型。html

Demo 1

public interface Generator {
    <T> T next();
}

第一種解決方法,在方法返回類型前加「<T>」使其成爲一個泛型方法。java

public interface Generator<T> {
    T next();
}

第二種解決方法,在接口名後加「<T>」使其成爲一個泛型接口。app

泛型類/接口在使用前,必須先指名參數類型,其中除了泛型方法外的泛型參數都將是所指定的類型。以下:ide

// 泛型接口與其子類
public interface Generator<T> {
    T next(T t);
    void print(T t);
}

public class SubGenerator implements Generator<String>{

    @Override
    public String next(String t) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void print(String t) {
        // TODO Auto-generated method stub
        
    }

}

// 含有泛型方法的接口及其子類
public interface Generator<T> {
    T next(T t);
    <U> void print(U t);
}

public class SubGenerator implements Generator<String>{

    @Override
    public String next(String t) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public <U> void print(U t) {
        // TODO Auto-generated method stub
        
    }

}

Demo 2

即靜態方法沒法訪問泛型類上定義的泛型,此時採用泛型方法可解決。測試

// 正確作法
public class StaticGenerator {
    public static <T> T rebey(T t) {
        return null;
    }
}

Demo 3

在《深刻理解Java虛擬機 JVM高級特性與最佳實踐(高清完整版)》P271 介紹了「當泛型碰見重載」的例子。得出的結論是:url

兩個方法若是有相同的名稱和特徵簽名,但返回值不一樣,那他們也是能夠合法地共存於一個Class文件中的。code

public String url(String s) {
    return "rebey.cn";
}

public int url(String s) {
    return 0;
}

然而以上代碼是沒法編譯經過的。由於此書出版時還未發佈JDK7,所以其實只有JDK1.6及如下才能編譯經過。隨着時間的推移,原來錯的可能因此仍是按咱們原來的理解來解讀重載就行了。同名方法參數個數、順序、類型不一樣,與返回值類型無關。htm

Demo 4

public class Utilities {
    public static <T> HashSet<T> create(int size) {
        return new HashSet<T>(size);
    }
     
    public static void print( HashSet<String> h) { 
        for (String s : h) System.out.println(s);
    }
}

public class ResultGerneric {
    public static void main(String[] args) {
        Utilities.print(Utilities.create(10));    // error in Java 5,6,7 ; fine in Java 8
    }
}

這是來自GenericsFAQ403中的一個例子。筆者在java7上測試了,如願的看到了錯誤提示:「The method print(HashSet<String>) in the type Utilities is not applicable for the arguments (HashSet<Object>)」。因爲Utilities.create方法未指定具體類型,默認轉爲Object,因此Utilities.print此時沒法接收其做爲String類型的參數。而在Java8版本的增長了類型推斷(type argument inference),可以根據賦值符號左邊值類型自動推斷出右邊。接口

此外,經過顯示指定參數類型也可以解決上述問題:get

public class ResultGerneric {
    public static void main(String[] args) {
        Utilities.print(Utilities.<String>create(10));//點操做符與方法名之間
    }
}

在《Think In Java》4th中泛型章節也提到了類似的例子(P363)。

說點什麼

經過幾個泛型的例子,咱們看到:隨着時間的推移,對的可能錯,錯的亦能對。

這不是頗有趣的一件事嗎?

待續...


更多有意思的內容,歡迎訪問筆者小站: rebey.cn

相關文章
相關標籤/搜索