L--Java泛型、泛型類、泛型接口和泛型方法

簡介

泛型出現的動機在於:爲了建立容器類java

泛型類

容器類應該算得上最具重用性類庫之一。先來看一下沒有泛型的狀況下的容器類如何定義:編程

public class Container {
    private String key;
    private String value;

    public Container(String k,String v) {
        key = k;
        value = v;
    }

    public String getKey() {
        return key;
    }

    public void setKey (String key) {
        this.key = key;
    }

    public String getValue() {
        return value;
    }

    public void setValue (String value) {
        this.value = value;
    }
}

Container類保存了一對key-value鍵值對,可是類型是定死的,也就說若是我想要建立一個鍵值對是String-Integer類型的,當前這個容器作不到的,必須再自定義。那麼這明顯重用性就很是低。app

 固然,能夠用Object來代替String,而且在javaSE5以前,咱們也只能這麼作,因爲Object是全部類型的基類,因此能夠直接轉型。可是這樣靈活性仍是不夠,由於仍是指定了類型,只不過此次指定的類型層級dom

更高而已,有沒有可能不指定類型?有沒有可能在運行時才知道具體的類型是什麼?ide

so,就出現了泛型。ui

public class Container<K,V> {
    private K key;
    private V value;

    public Container(K k,V v) {
        key = k;
        value = v;
    }

    public K getKey() {
        return key;
    }

    public void setKey (K key) {
        this.key = key;
    }

    public V getValue() {
        return value;
    }

    public void setValue (V value) {
        this.value = value;
    }
}

 

在編譯期,是沒法知道K和V具體是什麼類型,只有在運行時纔會真正根據類型來構造和分配內存。能夠看一下如今Container類對於不一樣類型的支持狀況:this

public class Main{

    public static void main (String[] args) {
        Container<String String> c1 = new Container<String, String>("name", "gudoumaoning");
        Container<String Integer> c1 = new Container<String, Integer>("age", "24");
        Container<Double Double> c1 = new Container<Double, Integer>(1.2, 1.3);

        System.out.println(c1.getKey() + ":" + c1.getValue());
        System.out.println(c2.getKey() + ":" + c2.getValue());
        System.out.println(c3.getKey() + ":" + c3.getValue());

    } 
}
//輸出:
name : gudoumaoning
age : 24
1.2 : 1.3

泛型接口

在泛型結構中,生成器是一個很好的理解,看以下的生成器接口定義:spa

public interface Generator<T> {
    public T next();
}
而後定義一個生成器類來實現這個接口:
public class FruiteGenerator implements Generator<String> {
    private String[] fruite = new String[] {"apple", "banana", "pear"};

    @Override
    public String next() {
        Random rand = new Random();
        return fruits[rand.nextInt(3)];
    }
}

 調用:code

public class Main {
    public static void main (String[] args) {
        FruiteGenerator fruitegenerator = new FruiteGenerator();

        System.out.println(fruitegenerator.next());
        System.out.println(fruitegenerator.next());
        System.out.println(fruitegenerator.next());
        System.out.println(fruitegenerator.next());
    }
}
//輸出:
apple
pear
pear
banana

泛型方法

一個基本原則是:不管什麼時候,只要你能作到,你就儘可能使用泛型方法。也就是說,若是泛型方法能夠取代將整個類泛化,那麼應該有限採用泛型方法。下面來看一個簡單的泛型方法的定義:blog

public class Main {

    public static <T> void out(T t) {
        System.out.println(t);
    }

    public static void main (String[] args) {
        out("gudoumaoning");
        out(123);
        out(11.11);
        out(false);
    }
}
能夠看到方法的參數完全泛化了,這個過程涉及到編譯器的類型推導和自動打包,也就是說原來須要咱們本身對類型進行的判斷和處理,如今編譯器幫咱們作了。這樣在定義方法的時候沒必要考慮之後到底要處理
哪些類型的參數,大大增長了編程 的靈活性。
 
再看一個泛型和可變參數的例子:
public class Main {

    public static <T> void out(T... args) {
        for (T t: args) {
            System.out.println(t);
        }        
    }

    public static void main (String[] args) {
        out("gudoumaoning", 123, 11.11, false);
    }
}

 輸出和前一段代碼相同,能夠看到泛型能夠和可變參數完美結合。

相關文章
相關標籤/搜索