深入 Java 泛型:基础应用与实战技巧
在 Java 泛型中,T
、E
、K
、V
、?
是常见的占位符符号,它们本质上没有区别,只是命名习惯不同,用于提高代码可读性。以下是详细解释和案例:
一、符号的常见含义
符号 | 典型用途 | 示例场景 |
---|---|---|
T | 通用类型(Type) | 泛型类、泛型方法的通用类型占位符 |
E | 集合元素(Element) | 集合类(如 List<E> 、Set<E> ) |
K | 键(Key) | 键值对中的键(如 Map<K, V> ) |
V | 值(Value) | 键值对中的值(如 Map<K, V> ) |
? | 通配符(Wildcard) | 表示未知类型(如 List<?> ) |
二、具体案例解析
1. T
(通用类型)
- 用途:表示任意类型,常见于泛型类或泛型方法。
- 示例:定义一个泛型类
Box<T>
,可以存放任意类型的对象。public class Box<T> {private T content;public void setContent(T content) {this.content = content;}public T getContent() {return content;} }// 使用示例 Box<String> stringBox = new Box<>(); stringBox.setContent("Hello"); Box<Integer> intBox = new Box<>(); intBox.setContent(100);
2. E
(集合元素)
- 用途:表示集合中的元素类型,常见于集合类。
- 示例:自定义一个简单的集合类
MyList<E>
。public class MyList<E> {private E[] elements;public void add(E element) { /* 添加元素 */ }public E get(int index) { /* 获取元素 */ } }// 使用示例 MyList<String> list = new MyList<>(); list.add("Java"); String element = list.get(0);
3. K
和 V
(键值对)
- 用途:表示键值对的键和值类型,常见于
Map
类。 - 示例:自定义一个泛型键值对类
Pair<K, V>
。public class Pair<K, V> {private K key;private V value;public Pair(K key, V value) {this.key = key;this.value = value;}public K getKey() { return key; }public V getValue() { return value; } }// 使用示例 Pair<String, Integer> pair = new Pair<>("Age", 25); String key = pair.getKey(); // "Age" int value = pair.getValue(); // 25
4. ?
(通配符)
- 用途:表示未知类型,常用于泛型方法的参数或返回值。
- 示例:编写一个方法,打印任意类型集合的内容。
public void printList(List<?> list) {for (Object item : list) {System.out.println(item);} }// 使用示例 List<String> strings = Arrays.asList("A", "B", "C"); List<Integer> numbers = Arrays.asList(1, 2, 3); printList(strings); // 输出 A, B, C printList(numbers); // 输出 1, 2, 3
三、通配符 ?
的进阶用法
1. 上界通配符 <? extends T>
- 用途:表示类型是
T
或其子类。 - 示例:处理数字集合(如
Integer
、Double
)。public double sum(List<? extends Number> numbers) {double sum = 0;for (Number num : numbers) {sum += num.doubleValue();}return sum; }// 使用示例 List<Integer> integers = Arrays.asList(1, 2, 3); List<Double> doubles = Arrays.asList(1.1, 2.2, 3.3); System.out.println(sum(integers)); // 6.0 System.out.println(sum(doubles)); // 6.6
2. 下界通配符 <? super T>
- 用途:表示类型是
T
或其父类。 - 示例:向集合中添加
T
类型的元素。public void addNumbers(List<? super Integer> list) {list.add(1);list.add(2); }// 使用示例 List<Number> numbers = new ArrayList<>(); addNumbers(numbers); // 可以添加 Integer 到 Number 集合
四、符号的命名习惯总结
符号 | 含义 | 典型场景 |
---|---|---|
T | 通用类型 | 泛型类、泛型方法 |
E | 集合元素 | List<E> 、Set<E> |
K | 键 | Map<K, V> |
V | 值 | Map<K, V> |
? | 未知类型(通配符) | 泛型参数中的灵活类型处理 |
五、注意事项
-
符号可自定义:
你可以使用其他字母(如A
、B
),但遵循习惯能提高代码可读性。public class MyGeneric<A, B> { /* ... */ } // 合法但不推荐
-
通配符
?
的限制:- 不能直接实例化泛型类型:
List<?> list = new ArrayList<?>();
❌ - 正确写法:
List<?> list = new ArrayList<>();
✅
- 不能直接实例化泛型类型:
-
类型擦除:
泛型信息在编译后会被擦除,运行时无法获取具体类型(如T
的实际类型)。
通过以上案例,可以清晰理解不同符号的用途和区别!