JAVA-泛型通配符的上界和下界
在 Java 泛型中,通配符(Wildcard) 用于表示未知的类型。为了增强灵活性和安全性,Java 提供了对通配符的上界(Upper Bound) 和 下界(Lower Bound) 的限制。
🟢 一、通配符概述
- 基本通配符:
?
- 表示未知类型。
- 示例:
List<?>
表示一个元素类型未知的列表。
⚠️ 使用
List<?>
后,不能向其中添加除null
外的任何元素(因为编译器不知道具体类型),但可以读取为Object
。
🔺 二、通配符的上界(Upper Bound Wildcard)
✅ 语法:
? extends T
- 表示“某个未知类型,它是
T
的子类型”。 - 适用于“只读不写”的场景。
✅ 示例:
List<? extends Number> list = new ArrayList<Integer>();
-
可以读取元素为
Number
类型:Number num = list.get(0);
-
❌ 不允许添加元素(除了
null
):list.add(123); // 编译错误!不知道实际类型是 Integer 还是 Double 等
✅ 用途:
- 当你只需要从集合中读取数据,并希望它能接受多种子类型时使用。
🔻 三、通配符的下界(Lower Bound Wildcard)
✅ 语法:
? super T
- 表示“某个未知类型,它是
T
的父类型”。 - 适用于“只写不读”的场景。
✅ 示例:
List<? super Integer> list = new ArrayList<Number>();
-
✅ 可以添加
Integer
类型的对象:list.add(10);
-
❌ 读取时只能作为
Object
类型:Object obj = list.get(0); // 无法知道具体是 Number、Object 还是其他父类
✅ 用途:
- 当你需要将某种具体类型的数据写入集合,并且该集合的类型必须是它的父类时使用。
🟡 四、对比总结
通配符形式 | 含义 | 可否添加元素 | 可否读取元素 | 典型用途 |
---|---|---|---|---|
? | 任意类型 | ❌ | ✅(作为 Object ) | 通用只读集合 |
? extends T | T 或其子类 | ❌ | ✅(作为 T ) | 读取特定类型的集合 |
? super T | T 或其父类 | ✅ | ✅(作为 Object ) | 写入特定类型的集合 |
🧠 小技巧:PECS 原则(Producer Extends, Consumer Super)
这是理解泛型通配符的经典原则:
- Producer(生产者) → 使用
extends
(只读) - Consumer(消费者) → 使用
super
(只写)
示例代码:
public static void copy(List<? extends Number> source,List<? super Number> dest) {for (Number number : source) {dest.add(number); // 写入到 dest}
}
📝 总结
- 使用
? extends T
来限定上界,适合读操作。 - 使用
? super T
来限定下界,适合写操作。 - 结合 PECS 原则,可以更安全地使用泛型集合。