Java 泛型通配符
什么是泛型通配符?
在Java泛型编程中,通配符是一种特殊的类型参数,用问号(?
)表示。通配符使泛型更加灵活,允许方法接受不同类型参数的集合,是处理类型安全和代码灵活性之间平衡的重要工具。
通配符的核心
通配符代表"某种未知类型",而不是所有类型。这种区别非常重要,因为它确保了类型安全。
为什么需要通配符?
假设我们有以下继承关系:
如果没有通配符,我们会遇到以下问题:
List<Animal> animals = new ArrayList<Animal>();
List<Cat> cats = new ArrayList<Cat>();
// 这行代码无法编译,即使Cat是Animal的子类
// animals = cats; // 编译错误
这是因为Java泛型是不可变的(invariant)。List<Cat>
不是List<Animal>
的子类型,即使Cat
是Animal
的子类型。通配符就是为了解决这个问题而设计的。
通配符的类型
Java中有三种类型的通配符:
- 无界通配符:
<?>
- 上界通配符:
<? extends Type>
- 下界通配符:
<? super Type>
让我们详细了解每一种。
1. 无界通配符(<?>
)
无界通配符表示"某种未知类型",当你只关心集合中对象的通用方法时使用。
示例:
public static void printCollection(Collection<?> c) {
for (Object element : c) {
System.out.println(element);
}
}
使用:
List<String> strings = Arrays.asList("Java", "Python", "C++");
List<Integer> numbers = Arrays.asList(1, 2, 3);
printCollection(strings); // 打印:Java, Python, C++
printCollection(numbers); // 打印:1, 2, 3
限制
使用无界通配符时,你不能向集合中添加元素(除了null),因为Java编译器无法确保添加的元素类型安全。
public static void addToCollection(Collection<?> c) {
// 这行代码无法编译
// c.add("element"); // 编译错误
// 只能添加null
c.add(null); // 允许
}