1:E
(Element,元素)
含义:通常代表集合中的元素类型。
常见使用方式:List<E> list;
使用场景:表示集合中的某个“元素”的类型。
举例说明:
public class MyList<E> {
private List<E> data = new ArrayList<>();
public void add(E element) {
data.add(element);
}
public E get(int index) {
return data.get(index);
}
}
2:T
(Type,类型)
含义:泛指某个类型,最常见的泛型类型名。
常见使用方式:
public class Box<T> {
private T value;
}
使用场景:用于类、方法、接口中泛指某种“类型”。
举例说明:
public class Box<T> {
private T value;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
}
使用 Box<Integer>、Box<String> 时,T 就分别是 Integer、String。
3:K
和 V
(Key 和 Value,键和值)
含义:K 代表 Key,V 代表 Value,常用于表示键值对结构。
常见使用方式:
Map<K, V> map;
使用场景:自定义 Map 或者类似结构时,表示键和值的泛型。
举例说明:
public class MyMap<K, V> {
private K key;
private V value;
public MyMap(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
}
4:?
(Wildcard,通配符)
含义:表示未知类型,用于“只读”场景,不能随意添加元素。
常见使用方式:
List<?> list; // 任意类型的列表
List<? extends Number> l; // 只能读 Number 及其子类
使用场景:参数接收泛型但不修改的情况(只读安全)。
举例说明:
public void printList(List<?> list) {
for (Object obj : list) {
System.out.println(obj);
}
}
public double sum(List<? extends Number> list) {
double total = 0;
for (Number num : list) {
total += num.doubleValue();
}
return total;
}
? extends
用于读取时安全;? super
用于写入时安全。
5:Java 泛型的进阶用法
主要包括 通配符的上下界(extends
和 super
),这是理解泛型真正威力的关键。
5.1:通配符 ? 的基本作用
? 表示未知类型。你可以理解为“我不关心具体是什么类型,只要能安全处理即可”。
常见写法:
List<?> list; // 表示任意类型的列表
但问题是:这种写法不能添加任何元素,只能读取元素为 Object。
5.2:上界通配符 ? extends T
—— 只能读,不能写
List<? extends Number>
表示:是某个 Number 的子类(比如 Integer、Double)的 List,但我们不确定是哪一个。
原因(只能读):
编译器无法确认泛型具体是什么类型,所以不能安全地添加元素(除了 null)。
但你可以放心地读,读取出来的对象至少是
Number
类型。
举例:
public double sum(List<? extends Number> list) {
double total = 0;
for (Number number : list) {
total += number.doubleValue(); // 安全读取
}
return total;
}
list.add(123); // ❌ 不允许,因为你不知道是 Integer 还是 Double
5.3:下界通配符 ? super T
—— 只能写,不能读
List<? super Integer>
表示:某种 Integer 的父类的 List,比如 List<Object>
或 List<Number>
。
原因(只能写):
我可以放心写入 Integer 或其子类。
但读取出来时只知道它是 Object(因为你不确定具体父类是什么)。
public void addIntegers(List<? super Integer> list) {
list.add(1); // ✅ 可以添加 Integer
list.add(1000); // ✅ 可以继续添加 Integer
// Integer 是安全的写入类型
}
以下是非法读法(不能读):
Integer value = list.get(0); // ❌ 错误:返回的是 Object
Object value = list.get(0); // ✅ 正确:只能当 Object 处理