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); // ✅ 可以添加 Integerlist.add(1000); // ✅ 可以继续添加 Integer// Integer 是安全的写入类型
}
以下是非法读法(不能读):
Integer value = list.get(0); // ❌ 错误:返回的是 Object
Object value = list.get(0); // ✅ 正确:只能当 Object 处理