public <T> void show(T t) { }
所謂泛型方法,就是在聲明方法時定義一個或多個類型形參。 泛型方法的用法格式以下:ide
修飾符<T, S> 返回值類型 方法名(形參列表){ 方法體 }
注意要點:this
class Demo{ public <T> T fun(T t){ // 能夠接收任意類型的數據 return t ; // 直接把參數返回 } }; public class GenericsDemo26{ public static void main(String args[]){ Demo d = new Demo() ; // 實例化Demo對象 String str = d.fun("湯姆") ; // 傳遞字符串 int i = d.fun(30) ; // 傳遞數字,自動裝箱 System.out.println(str) ; // 輸出內容 System.out.println(i) ; // 輸出內容 } };
先來看一個案例設計
/** * 泛型接口的定義格式: 修飾符 interface 接口名<數據類型> {} */ public interface Inter<T> { public abstract void show(T t) ; } /** * 子類是泛型類 */ public class InterImpl<E> implements Inter<E> { @Override public void show(E t) { System.out.println(t); } } Inter<String> inter = new InterImpl<String>() ; inter.show("hello") ;
而後看看源碼中泛型的使用,下面是JDK 1.5 之後,List接口,以及ArrayList類的代碼片斷。code
//定義接口時指定了一個類型形參,該形參名爲E public interface List<E> extends Collection<E> { //在該接口裏,E能夠做爲類型使用 public E get(int index) {} public void add(E e) {} } //定義類時指定了一個類型形參,該形參名爲E public class ArrayList<E> extends AbstractList<E> implements List<E> { //在該類裏,E能夠做爲類型使用 public void set(E e) { ....................... } }
這就是泛型的實質:容許在定義接口、類時聲明類型形參,類型形參在整個接口、類體內可當成類型使用,幾乎全部可以使用普通類型的地方均可以使用這種類型形參。對象
泛型類派生子類繼承
public class A extends Container<K, V>{}
public class A extends Container<Integer, String>{}
public class A extends Container{}
定義一個容器類,存放鍵值對key-value,鍵值對的類型不肯定,可使用泛型來定義,分別指定爲K和V。接口
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 V getValue() { return value; } public void setKey() { this.key = key; } public void setValue() { this.value = value; } }
在使用Container類時,只須要指定K,V的具體類型便可,從而建立出邏輯上不一樣的Container實例,用來存放不一樣的數據類型。字符串
public static void main(String[] args) { Container<String,String> c1=new Container<String ,String>("name","hello"); Container<String,Integer> c2=new Container<String,Integer>("age",22); Container<Double,Double> c3=new Container<Double,Double>(1.1,1.3); System.out.println(c1.getKey() + " : " + c1.getValue()); System.out.println(c2.getKey() + " : " + c2.getValue()); System.out.println(c3.getKey() + " : " + c3.getValue()); }
在JDK 1.7 增長了泛型的「菱形」語法:Java容許在構造器後不須要帶完成的泛型信息,只要給出一對尖括號(<>)便可,Java能夠推斷尖括號裏應該是什麼泛型信息。 以下所示:get
Container<String,String> c1=new Container<>("name","hello"); Container<String,Integer> c2=new Container<>("age",22);
public class Person { public <T> Person(T t) { System.out.println(t); } }
public static void main(String[] args){ //隱式 new Person(22); //顯示 new<String> Person("hello"); }
這裏惟一須要特殊註明的就是:編譯器
若是構造器是泛型構造器,同時該類也是一個泛型類的狀況下應該如何使用泛型構造器:由於泛型構造器能夠顯式指定本身的類型參數(須要用到菱形,放在構造器以前),而泛型類本身的類型實參也須要指定(菱形放在構造器以後),這就同時出現了兩個菱形了,這就會有一些小問題,具體用法再這裏總結一下。
如下面這個例子爲表明
public class Person<E> { public <T> Person(T t) { System.out.println(t); } }
這種用法:Person<String> a = new <Integer>Person<>(15);這種語法不容許,會直接編譯報錯!
通配符的設計存在必定的場景,例如在使用泛型後,首先聲明瞭一個Animal的類,然後聲明瞭一個繼承Animal類的Cat類,顯然Cat類是Animal類的子類,可是List卻不是List的子類型,而在程序中每每須要表達這樣的邏輯關係。爲了解決這種相似的場景,在泛型的參數類型的基礎上新增了通配符的用法。
上界通配符顧名思義,<? extends T>表示的是類型的上界【包含自身】,所以通配的參數化類型多是T或T的子類。
它表示集合中的全部元素都是Animal類型或者其子類 List<? extends Animal>
這就是所謂的上限通配符,使用關鍵字extends來實現,實例化時,指定類型實參只能是extends後類型的子類或其自己。
//Cat是其子類 List<? extends Animal> list = new ArrayList<Cat>();
下界通配符<? super T>表示的是參數化類型是T的超類型(包含自身),層層至上,直至Object
它表示集合中的全部元素都是Cat類型或者其父類 List <? super Cat>
這就是所謂的下限通配符,使用關鍵字super來實現,實例化時,指定類型實參只能是extends後類型的子類或其自己。
例如:
//Shape是其父類 List<? super Cat> list = new ArrayList<Animal>();
當聲明泛型類的實例時,傳遞的類型參數必須是引用類型,不能使用基本類型
User<int,double> user=new User<>(1,10,0);
如何解決