如何理解java通配符
理解Java通配符的基本概念
Java通配符(?)用于泛型中表示未知类型,主要解决泛型类型的协变性问题。通配符允许更灵活地处理泛型类型之间的关系,常见于集合类操作或方法参数中。
通配符的分类
通配符分为三类:无界通配符、上界通配符和下界通配符。
无界通配符(<?>)
表示完全未知的类型,通常用于泛型类的简单操作(如查询)。例如:
List<?> list; // 可接受任何类型的List,但只能读取为Object
上界通配符(<? extends T>)
表示类型是T或其子类,支持安全的读取操作(协变)。例如:
List<? extends Number> numbers = new ArrayList<Integer>(); // 允许
Number num = numbers.get(0); // 安全读取
下界通配符(<? super T>)
表示类型是T或其父类,支持安全的写入操作(逆变)。例如:
List<? super Integer> integers = new ArrayList<Number>(); // 允许
integers.add(42); // 安全写入
通配符的使用场景
- 读取数据:使用
<? extends T>确保读取的类型是T的子类。 - 写入数据:使用
<? super T>确保可以安全添加T类型的元素。 - 兼容性:无界通配符
<?>用于不需要类型依赖的通用代码。
通配符的限制
- 上界通配符不允许写入(除
null外),因为具体类型未知。 - 下界通配符不允许读取为具体类型(只能读取为
Object)。
示例对比
// 上界通配符:只读
List<? extends Number> nums = Arrays.asList(1, 2, 3);
Number n = nums.get(0); // 正确
// nums.add(1); // 编译错误,无法写入
// 下界通配符:可写
List<? super Integer> list = new ArrayList<Number>();
list.add(100); // 正确
// Integer i = list.get(0); // 编译错误,只能转为Object
通配符与泛型方法的区别
通配符用于声明变量或参数的类型灵活性,而泛型方法(如<T> void foo(List<T> list))通过类型参数T在方法内保持类型一致性。两者可结合使用以实现更复杂的需求。

通过理解通配符的边界和读写规则,可以更灵活地设计泛型API,同时确保类型安全。





