泛型出現的動機在於:爲了建立容器類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); } }
輸出和前一段代碼相同,能夠看到泛型能夠和可變參數完美結合。