定義
在編譯時期就對元素的類型進行檢查,一旦發現不匹配就編譯失敗。在編譯時泛型就被擦除了,所以無法在運行時得知其類型參數的類型。通過泛型可以定義類型安全的數據結構(類型安全),而無須使用實際的數據類型(可擴展),這能夠顯著提高性能並得到更高質量的代碼(高性能),因爲可以重用數據處理算法,而無須複製類型特定的代碼(可重用)。
泛型可以定義在類,接口,方法上
- 定義時尖括號裏的每個元素都代指一種未知類型
- 尖括號的位置非常講究,必須在類名之後或者方法返回值之前
- 泛型在定義處只具備Object方法的能力
- 基本數據類型不能作爲泛型參數
// 泛型接口
public interface Genericity<T> {
T test();
}
public class Son implements Genericity<Integer> {
@Override
public Integer test() {
return null;
}
}
// 泛型類 在編譯時是無法知道K和V具體是什麼類型,只有在運行時纔會真正根據類型來構造和分配內存。
@Data
public class Container<K, V> {
private K key;
private V value;
public Container(K key, V value) {
this.key = key;
this.value = value;
}
// 這裏不能用static修飾 靜態方法無法訪問類上定義的泛型。
public K test(V v){
return null;
}
// String不等於java.lang.String,只是一個自定義的泛型類型
public static <String> String test2(String str){
return str;
}
public static void main(String[] args) {
// 這裏如果傳入的是Integer類型,編譯不會報錯,運行會報ClassCastException
Container<String, String> container = new Container(1, 2);
System.out.println(container.getKey());
System.out.println(container.getValue());
}
}
泛型的限定
<? extends E>
泛型上限 接收E或者E的子類,一般在存儲元素時使用上限,取值時用E來接收,不會存在類型安全問題
public static void printCollection(List<? extends Number> list){
Number number = list.get(0);
}
<? super E>
泛型下限 接收E或者E的父類,從集合取值時可以用E或者E的父類接收
public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<>(comparator));
}
泛型擦除
List<String> list = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
System.out.println(list.getClass() == list2.getClass()); // true
泛型擦除帶來的問題
- 不能使用泛型來重載方法
- 2.不能catch同一個異常的不同泛型實例
- 3.不同泛型類的靜態變量是共享的
- 4.泛型間不存在繼承關係,不能使用List 來接收List類型的參數