返回

泛型编程中的问号类型通配符,理解extends和super的区别

java

泛型编程中的问号类型通配符

简介

泛型编程是 Java 中一种强大的技术,它使我们能够创建可处理多种数据类型的代码。问号 (?) 类型通配符是泛型编程中的一种重要工具,它允许我们表示通配符类型,该类型可以匹配任何类型或其子类型。

语法

问号类型的通配符在泛型声明中使用,遵循以下语法:

  • ? extends T:匹配 T 或其任何子类型。
  • ? super T:匹配 T 或其任何父类型。

理解 extends 和 super

  • extends T: 表示通配符类型可以是 T 或其任何子类型。这意味着我们可以将子类型的对象存储在声明为 ? extends T 的列表中。例如,如果我们声明 List<? extends Animal>,则我们可以将 DogCat 对象存储在该列表中,因为它们是 Animal 的子类型。
  • super T: 表示通配符类型可以是 T 或其任何父类型。这意味着我们可以将父类型的对象存储在声明为 ? super T 的列表中。例如,如果我们声明 List<? super Dog>,则我们可以将 DogAnimal 对象存储在该列表中,因为 DogAnimal 的父类型。

优点

使用问号类型通配符可以带来以下优点:

  • 灵活性: 允许我们操作各种类型对象,而无需指定确切的类型。
  • 代码重用: 使我们能够编写可重用的代码,该代码可以在处理不同类型时工作。
  • 类型安全: 确保我们不会将不兼容的类型添加到列表中。

注意事项

使用问号类型通配符时需要注意以下事项:

  • 对于声明为 ? extends T 的列表,我们不能向其中添加元素,因为我们不知道确切的类型。
  • 从声明为 ? extends T 的列表中读取元素时,我们必须将它们强制转换为特定的类型。

示例

class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

List<? extends Animal> animalList = new ArrayList<>();

animalList.add(new Dog()); // OK,因为 Dog 是 Animal 的子类型
animalList.add(new Cat()); // OK,因为 Cat 是 Animal 的子类型

for (Animal animal : animalList) {
    // 需要强制转换为特定的类型
    Dog dog = (Dog) animal;
    Cat cat = (Cat) animal;
}

结论

问号类型通配符是 Java 泛型编程中一个强大的工具,可以为我们提供更大的灵活性、代码重用和类型安全性。通过理解 extendssuper 之间的区别,我们可以在代码中有效地使用问号通配符。

常见问题解答

  1. 问号类型通配符和通配符的区别是什么?
    通配符只能匹配任何对象类型,而问号类型通配符可以匹配任何类型或其子类型或父类型。
  2. 我什么时候应该使用 ? extends T? super T
    使用 ? extends T 当你需要处理子类型对象时,使用 ? super T 当你需要处理父类型对象时。
  3. 我是否可以向 ? extends T 列表添加元素?
    不,你不能向 ? extends T 列表添加元素,因为你不知道确切的类型。
  4. ? extends T 列表中读取元素时,我应该怎么做?
    ? extends T 列表中读取元素时,你需要将它们强制转换为特定的类型。
  5. 使用问号类型通配符的潜在缺点是什么?
    使用问号类型通配符的潜在缺点是它可能会导致代码中出现一些不必要的类型转换,从而降低了效率。