🤟致敬讀者
- 🟩感謝閱讀🟦笑口常開🟪生日快樂?早點睡覺
📘博主相關
- 🟧博主信息🟨博客首頁🟫專欄推薦🟥活動信息
文章目錄
- JavaSE核心知識點02面向對象編程02-06(泛型)
- **一、為什么需要泛型?**
- **二、泛型的基本語法**
- **1. 定義泛型類/接口**
- **2. 使用泛型類**
- **三、泛型方法**
- **四、泛型通配符 `?`**
- **1. 無界通配符 `<?>`**
- **2. 上界通配符 `<? extends T>`**
- **3. 下界通配符 `<? super T>`**
- **PECS 原則**(Producer Extends, Consumer Super)
- **五、類型擦除(Type Erasure)**
- **六、泛型的限制與注意事項**
- **七、典型應用場景**
- **八、代碼示例:自定義泛型棧**
- **九、總結**
📃文章前言
- 🔷文章均為學習工作中整理的筆記。
- 🔶如有錯誤請指正,共同學習進步。
JavaSE核心知識點02面向對象編程02-06(泛型)
泛型(Generics)是 Java 中非常重要的特性,它讓代碼更安全、更靈活。下面用通俗易懂的方式為你講解,包含代碼示例和核心概念。
一、為什么需要泛型?
問題:假設你要寫一個可以存放任何類型數據的容器(比如一個盒子)。沒有泛型時,代碼可能這樣寫:
class Box {private Object data; // 用 Object 存儲任意類型public void setData(Object data) {this.data = data;}public Object getData() {return data;}
}
缺陷:
- 取出數據時需要強制類型轉換,容易出錯。
- 無法限制放入的類型,可能混入不同類型的數據。
泛型的解決方案:讓容器在定義時聲明它能存儲的數據類型。
Box<String> box = new Box<>(); // 只能存 String
box.setData("Hello"); // 正確
// box.setData(123); // 編譯報錯!
String data = box.getData(); // 無需強制轉換
二、泛型的基本語法
1. 定義泛型類/接口
在類名后加<T>
,T
是類型參數(可以是任意標識符,如E
, K
, V
等)。
class Box<T> { // T 表示“某種類型”private T data;public void setData(T data) {this.data = data;}public T getData() {return data;}
}
2. 使用泛型類
創建對象時指定具體類型:
Box<String> stringBox = new Box<>(); // 存儲 String
Box<Integer> intBox = new Box<>(); // 存儲 Integer
三、泛型方法
即使類不是泛型,方法也可以獨立聲明泛型:
public class Utils {// 泛型方法:在返回類型前加 <T>public static <T> void printArray(T[] array) {for (T element : array) {System.out.println(element);}}
}// 使用
Integer[] intArray = {1, 2, 3};
Utils.printArray(intArray); // 自動推斷類型為 Integer
四、泛型通配符 ?
用于處理未知類型,常見于方法參數或集合操作。
1. 無界通配符 <?>
表示接受任何類型:
public static void printList(List<?> list) {for (Object elem : list) {System.out.println(elem);}
}
2. 上界通配符 <? extends T>
表示類型是T
或其子類:
// 只能讀取元素(因為元素是 Animal 或其子類)
public static void processAnimals(List<? extends Animal> animals) {for (Animal animal : animals) {animal.eat();}
}
3. 下界通配符 <? super T>
表示類型是T
或其父類:
// 可以寫入元素(因為容器是 T 的父類)
public static void addNumbers(List<? super Integer> list) {list.add(123); // 允許添加 Integer
}
PECS 原則(Producer Extends, Consumer Super)
- 生產者(Producer):使用
<? extends T>
,只能讀取。 - 消費者(Consumer):使用
<? super T>
,只能寫入。
五、類型擦除(Type Erasure)
Java 泛型在編譯后會被擦除為原始類型(如Object
),這是為了兼容舊版本 Java。例如:
List<String> list = new ArrayList<>();
// 編譯后實際是:List list = new ArrayList();
影響:
- 運行時無法獲取泛型的具體類型(如
T
的實際類型)。 - 不能創建泛型數組(如
new T[]
)。 - 泛型類型不能是基本類型(如
List<int>
錯誤,要用List<Integer>
)。
六、泛型的限制與注意事項
-
不能實例化類型參數:
// 錯誤!new T() 是非法的 T data = new T();
-
靜態成員不能使用泛型類型:
class Box<T> {// 錯誤!靜態變量不能是泛型private static T staticData; }
-
泛型與繼承的關系:
List<String>
不是List<Object>
的子類。- 但
ArrayList<String>
是List<String>
的子類。
七、典型應用場景
- 集合框架(如
ArrayList<E>
、HashMap<K,V>
)。 - 工具類(如
Collections
中的泛型方法)。 - 自定義通用數據結構(如棧、隊列、鏈表)。
八、代碼示例:自定義泛型棧
class Stack<T> {private List<T> elements = new ArrayList<>();public void push(T element) {elements.add(element);}public T pop() {if (elements.isEmpty()) {throw new EmptyStackException();}return elements.remove(elements.size() - 1);}
}// 使用
Stack<Integer> stack = new Stack<>();
stack.push(1);
int num = stack.pop(); // 無需強制轉換
九、總結
- 核心目的:提高代碼的類型安全性和復用性。
- 關鍵語法:
<T>
定義泛型,?
處理未知類型。 - 注意事項:類型擦除、通配符的使用場景、PECS原則。
掌握泛型后,你將能寫出更健壯、更靈活的 Java 代碼!
📜文末寄語
- 🟠關注我,獲取更多內容。
- 🟡技術動態、實戰教程、問題解決方案等內容持續更新中。
- 🟢《全棧知識庫》技術交流和分享社區,集結全棧各領域開發者,期待你的加入。
- 🔵?加入開發者的《專屬社群》,分享交流,技術之路不再孤獨,一起變強。
- 🟣點擊下方名片獲取更多內容🍭🍭🍭👇