Java進階之泛型

打好基礎的第一天

java知識是做爲Android開發的語言基礎,雖然如今咱們已經推出了kotlin,可是基於如下緣由咱們仍是須要好好緊緊掌握javajava

  • kotlin也須要編譯成爲java運行;
  • 目前大量的第三方庫和繼承與前任的代碼都是java所寫的;
  • Java語言應用不只僅在Android,就是在後臺開發中也是一個最流行的語言;
  • 大公司面試都要求咱們有紮實的Java語言基礎。因此,請你們不要輕視提升本身Java基礎的機會,請你們認真學習,作好筆記,爭取取得更大的進步。

爲何須要泛型面試

public int addInt(int x, int y){
    return x+y;
}
public float addInt(float x, float y){
    return x+y;
}

public static void main(String[] args){
    List list = new ArrayList();
    lisr.add("1");
    lisr.add("2");
    lisr.add(3);
    for(int i = 0; i < list.size(); i++){
        String name = (String) list.get(i);
        System.out.println("value");
    }
}
// 運行時會出現「java.lang.ClassCastException」

複製代碼

實際開發,常常有數值求和的需求.即不一樣的數據類型執行同樣的邏輯 作同樣的事情.這個時候就須要泛型出馬啦.學習

在如上的編碼過程當中,咱們發現主要存在兩個問題:this

  • 當咱們將一個對象放入集合中,集合不會記住此對象的類型,當再次從集合中取出此對象時,改對象的編譯類型變成了Object類型,但其運行時類型任然爲其自己類型。
  • 所以,//1處取出集合元素時須要人爲的強制類型轉化到具體的目標類型,且很容易出現「java.lang.ClassCastException」異常。

因此泛型的好處就是:編碼

  • 適用於多種數據類型執行相同的代碼
  • 泛型中的類型在使用時指定, 不須要強制類型轉換

泛型類和泛型接口

泛型,即「參數化類型」。一提到參數,最熟悉的就是定義方法時有形參,而後調用此方法時傳遞實參。那麼參數化類型怎麼理解呢? 顧名思義,就是將類型由原來的具體的類型參數化,相似於方法中的變量參數,此時類型也定義成參數形式(能夠稱之爲類型形參),而後在使用/調用時傳入具體的類型(類型實參)。 泛型的本質是爲了參數化類型(在不建立新的類型的狀況下,經過泛型指定的不一樣類型來控制形參具體限制的類型)。也就是說在泛型使用過程當中,操做的數據類型被指定爲一個參數,這種參數類型能夠用在類、接口和方法中,分別被稱爲泛型類、泛型接口、泛型方法。 引入一個類型變量T(其餘大寫字母均可以,不過經常使用的就是T,E,K,V等等),而且用<>括起來,並放在類名的後面。泛型類是容許有多個類型變量的。spa

public class NormalGeneric<T>{
    private T data;
    public NormalGeneric(){
    }
    public NormalGeneric(T data){
        this();
        this.data = data;
    }
}
public class NormalGeneri2c<T, V>{
    private T data;
    private V result;
    public NormalGeneric2(){
    }
}
public interface Generator<T>{
    public T next();
}
複製代碼

泛型接口與泛型類的定義基本相同。code

實現泛型接口的類 有兩種方法方式orm

//不傳入泛型實參時
public class GeneratorImpl<T> implement Generator<T>{
    public T next(){
        return T;
    }
}
// 傳入泛型實參
public class GeneratorImpl2 implement Generator<String>{
    public String next(){
        return "ok";
    }
}
複製代碼

泛型方法

泛型方法, 是在調用方法的時候指明泛型的具體類型 ,泛型方法能夠在任何地方和任何場景中使用,包括普通類和泛型類。注意泛型類中定義的普通方法和泛型方法的區別。對象

public class GeneratorMenhod<T>{
    private T data;
    // 這不是一個泛型方法 這只是在泛型類中的一個普通方法 只不過是它的返回類型是泛型類中的類型.
    public T get(){
        return data;
    }
    
    // 這纔是一個泛型方法 在public與返回值指尖的<T>不可缺乏
    public <T> T textMetgod(T...a){
        return a[a.length/2];
    }
}
複製代碼

限定類型變量

有時候,咱們須要對類型變量加以約束,好比計算兩個變量的最小,最大值。繼承

public <T> T textMetgod(T a, T b){
        return a.compareTo(b) > 0 ? a : b;
    }
    // 編譯報錯 提示沒有a compareTo方法
複製代碼

如何確保傳入的兩個變量必定有compareTo方法?那麼解決這個問題的方案就是將T限制爲實現了接口Comparable的類

/* T表示應該綁定類型的子類型,Comparable表示綁定類型,子類型和綁定類型能夠 是類也能夠是接口。*/
    public <T extends Comparable> T min(T a, T b){
        return a.compareTo(b) > 0 ? a : b;
    }
    
    /* 若是這個時候,咱們試圖傳入一個沒有實現接口Comparable的類的實例,將會發生編譯錯誤。*/
    
    public static void main(String[] args){
        min(22, 22);// 成功比較
        min("a", "b");// 成功比較
        min(new Test(), new Test()); // 提示報錯
    }
複製代碼

同時extends左右都容許有多個,如 T,V extends Comparable & Serializable 注意限定類型中,只容許有一個類,並且若是有類,這個類必須是限定列表的第一個。 這種類的限定既能夠用在泛型方法上也能夠用在泛型類上

泛型的約束性和侷限性

相關文章
相關標籤/搜索