泛型就是標籤,加了泛型,就至關於加了標籤,這個容器就只能放這一類物品。java
把元素的類型設參數,這個類型參數叫作泛型。Collection<E>,List<E>,ArrayList<E>
這個<E>
就是類型參數,即泛型。數據庫
所謂泛型,就是容許在定義類、接口時經過一個標識表示類中某個屬性的類型或者是某個方法的返回值及參數類型。這個類型參數將在使用時(例如, 繼承或實現這個接口,用這個類型聲明變量 、建立對象時)肯定(即傳入實 際的類型參數,也稱爲類型實參)。數組
JDK1.5時引入。安全
② 在實例化集合類時,能夠指明具體的泛型類型。ide
③ 指明完之後,在集合類或接口中凡是定義類或接口時,內部結構(好比:方法、構造器、屬性等)使用到類的泛型的位置,都指定爲實例化的泛型類型。this
好比:add(E e) --->實例化之後:add(Integer e)。code
④ 注意點:泛型的類型必須是類,不能是基本數據類型。須要用到基本數據類型的位置,拿包裝類替換。對象
⑤ 若是實例化時,沒有指明泛型的類型。默認類型爲java.lang.Object類型。繼承
⑥在JDK7中新特性:類型推斷接口
List<String> list = new List<>();
後面的泛型能夠省略/** * 自定義泛型類 */ public class MyGeneric<T> { String name; int age; T decs;//能夠把他當作一個類來看,可是並非類,而是參數 public MyGeneric() { } //帶參構造器 public MyGeneric(String name, int age, T decs) { this.name = name; this.age = age; this.decs = decs; } //get()方法 public T getDecs() { return decs; } //set()方法 public void setDecs(T decs) { this.decs = decs; } //toString()方法 @Override public String toString() { return "MyGeneric{" + "name='" + name + '\'' + ", age=" + age + ", decs=" + decs + '}'; } }
class Father<T1, T2>{ } //子類不保留父類的泛型 //1)沒有類型,擦除--->這時,子類不是泛型 class Son1 extends Father{//等價於class Son extends Father<Object,Object>{ } //2)具體類型--->這時,子類不是泛型 class son2 extends Father<Integer, String>{ } //子類保留父類的泛型 //1)所有保留 class Son3<T1, T2> extends Father<T1, T2>{ } //2)部分保留 class Son4<T2> extends Father<Integer, T2>{ } //固然子類也能夠加上本身的新的泛型類型
注意點
泛型類裏的泛型是以參數的形式存在的。
能夠有多個參數:<T1,T2,T3>
聲明構造器時
public MyGeneric() {}
public MyGeneric(String name, int age, T decs) {
泛型不一樣的引用不能相互賦值
ArrayList<String> list1 = new ArrayList<>(); ArrayList<Integer> list2 = new ArrayList<>(); list1 = list2;//這樣是錯誤的!
泛型若是不指定,就會被擦除,泛型對應的類型按照Object處理,但不等價於Object。
在類/接口上聲明的泛型,在本類或本接口中即表明某種類型,能夠做爲非靜態 屬性的類型、非靜態方法的參數類型、非靜態方法的返回值類型。但在靜態方法中不能使用類的泛型。(由於,靜態方法隨着類的加載而加載,而泛型是在實例化的時候指定,晚於靜態方法出生)
異常類不能聲明爲泛型的。
若是想在構造器中初始化一個T類型的數組,要寫做:
T[] t = (T[])new Object[capacity]
public static <E> List<E> copyFromArrayToList(E[] arr){ //這裏的第一個<E>是爲了避免讓編譯器把E當作是一個咱們自定義的類 ArrayList<E> list = new ArrayList<>(); for(E e : arr){ list.add(e); } return list; }
鏈接數據庫時,操做數據庫中的表的記錄
DAO類:定義了數據庫不一樣表的一些共性操做的類
public class DAO<T> {}
CustomerDAO:定義了專門操做Customer表的類
public class CustomerDAO extends DAO<Customer>{}
//泛型方法舉例 /* 返回的東西是不肯定的,好比 需求1:表中有多少條記錄 需求2:獲取工資最大值 */ public <E> E getSomething(){ return null; }
例如,String是Object的子類,可是List<String >並非List<Object> 的子類。
同理在方法參數中也同樣適用。這樣就致使一個問題,同一功能的方法要重載不少次。B<T>仍然是A<T>
的子類。通配符用 ?
來表示,含義爲:類A是類B的父類,G<A> G<B>
並不存在什麼關係,兩者的共同父類是:G<?>
。這樣就沒必要重載那麼多功能相同的方法了。
?
能夠的範圍能夠理解爲: (無窮小,無窮大)? extends A
的範圍就能夠理解爲:小於等於,即(無窮小,A]? super A
的範圍就能夠理解爲:大於等於,即[A,無窮大)