返回

通配符类型 <? super T> 和 <? extends T> 的深入解析:揭秘泛型类型

java

泛型类型:解开 <? super T> 和 <? extends T> 之谜

前言

泛型类型是 Java 中强大的工具,它允许你创建可以处理不同类型对象的类和方法。在泛型类型中,通配符类型,例如 <? super T><? extends T> ,用于指定类型变量 T 的上下界。在本文中,我们将深入探讨这两种通配符类型的区别,并了解何时使用它们。

<? super T>:超类型

<? super T> 指定 T 的超类型。换句话说,它允许你使用 <? super T> 类型的变量来引用 T 类型的对象或其任何超类型(父类或接口)的对象。例如,假设我们有一个父类 Animal 和一个子类 Dog。那么:

  • List<? super Dog> 可以引用 List<Animal>List<Dog> 对象。
  • 不能 引用 List<Object> 或任何其他不包含 Animal 类型对象的列表。

用途:

<? super T> 非常适合以下情况:

  • 当你想从一个超级类型集合中读取元素时。
  • 当你想将一个元素添加到一个超类型列表中时。

<? extends T>:子类型

<? extends T> 指定 T 的子类型。换句话说,它允许你使用 <? extends T> 类型的变量来引用 T 类型的对象或其任何子类型(子类或实现类)的对象。延续之前的示例:

  • List<? extends Animal> 可以引用 List<Animal>List<Dog> 对象。
  • 不能 引用 List<Object> 或任何其他不派生自 Animal 类型对象的列表。

用途:

<? extends T> 适用于以下情况:

  • 当你想将一个元素添加到一个子类型列表中时。
  • 当你想从一个子类型集合中获取一个元素时。

<? super T> 和 <? extends T> 的区别

  • <? super T> 允许你添加 T 类型的对象,因为 T 的超类型也可以添加。
  • <? extends T> 不允许 你添加 T 类型的对象,因为 T 的子类型不能添加。

示例代码

// 超类型通配符
List<? super Dog> list1 = new ArrayList<>();
list1.add(new Dog()); // 允许添加 Dog 对象
list1.add(new Animal()); // 允许添加 Animal 对象

// 子类型通配符
List<? extends Animal> list2 = new ArrayList<>();
list2.add(new Animal()); // 不允许添加 Animal 对象
list2.add(new Dog()); // 不允许添加 Dog 对象

结论

理解 <? super T><? extends T> 通配符类型对于有效使用 Java 泛型至关重要。通过了解它们之间的区别,你可以创建灵活且可重用的代码。

常见问题解答

1. 什么时候使用 <? super T>?
当你需要一个可以引用 T 类型的对象或其超类型对象的列表或集合时。

2. 什么时候使用 <? extends T>?
当你需要一个只能引用 T 类型的对象或其子类型对象的列表或集合时。

3. <? super T> 可以添加 T 类型的对象吗?
是的,它可以。

4. <? extends T> 可以添加 T 类型的对象吗?
不,它不能。

5. 通配符类型有什么好处?
它们提供灵活性,让你可以编写可处理不同类型对象的代码。