第 28 章:泛型深入
学习目标
- 理解泛型的作用
- 掌握泛型类、泛型方法
- 理解类型擦除和通配符
一、为什么需要泛型?
java
// ❌ 没有泛型:每次都要强转,编译期不检查
List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0); // 必须强转
list.add(123); // ❌ 可以混入 Integer
// ✅ 有泛型:编译期检查
List<String> list = new ArrayList<>();
list.add("hello");
// list.add(123); // ❌ 编译报错
String s = list.get(0); // 自动推断,无需强转二、泛型类
java
public class Box<T> { // ① 类型参数 T
private T content; // ② 通用类型字段
public void put(T item) {
this.content = item;
}
public T get() { // ③ 返回通用类型
return content;
}
}
Box<String> stringBox = new Box<>();
stringBox.put("hello");
String s = stringBox.get();
Box<Integer> intBox = new Box<>();
intBox.put(123);
Integer i = intBox.get();多类型参数
java
public class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
// getter, setter, toString
}
Pair<String, Integer> pair = new Pair<>("age", 18);三、泛型方法
java
public class ArrayUtils {
// ① 泛型方法:在返回类型前声明 <T>
public static <T> T getFirst(T[] arr) {
return arr[0];
}
public static <T> void swap(T[] arr, int i, int j) {
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
String[] strs = {"A", "B", "C"};
String first = ArrayUtils.getFirst(strs);
ArrayUtils.swap(strs, 0, 2);四、通配符
java
List<?> unbounded; // 任意类型
List<? extends Number> upperBounded; // Number 及其子类
List<? super Integer> lowerBounded; // Integer 及其父类PECS 原则
| 场景 | 用 |
|---|---|
| Producer(只读) | <? extends T> 上界通配 |
| Consumer(只写) | <? super T> 下界通配 |
java
// Producer:只能读
public void process(List<? extends Number> list) {
for (Number n : list) { // ✅ 读
System.out.println(n);
}
// list.add(1); // ❌ 不能写
}
// Consumer:只能写
public void fill(List<? super Integer> list) {
list.add(1); // ✅ 写
// Integer i = list.get(0); // ❌ 不能读
}五、类型擦除
泛型只在编译期存在,运行时被擦除:
java
List<String> strList = new ArrayList<>();
List<Integer> intList = new ArrayList<>();
System.out.println(strList.getClass() == intList.getClass()); // true
System.out.println(strList.getClass()); // class java.util.ArrayList六、本章小结
| 要点 | 关键 |
|---|---|
| 泛型 | 编译期类型检查,避免强转 |
| 泛型类 | class Box<T> |
| 泛型方法 | <T> T getFirst(T[]) |
| 通配符 | ? / ? extends T / ? super T |
| 类型擦除 | 运行时无泛型信息 |
| PECS | Producer 用 extends,Consumer 用 super |
动手练习
练习 1:基础题
实现一个 Pair<K, V> 泛型类。
练习 2:进阶题
实现一个泛型方法 max(T[] arr, Comparator<T> cmp),返回数组中的最大值。
下一章:第 29 章:异常处理基础 →