MST

星途 面试题库

面试题:Java泛型通配符的高级应用场景

在Java泛型中,通配符有?、? extends T 和? super T 等形式。请举例说明? extends T 和? super T 在实际编程中的高级应用场景,比如在集合操作、方法参数传递等方面,并且解释它们的区别和使用原则。
37.3万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

1.? extends T 的应用场景及解释

  • 应用场景 - 集合操作:假设有一个动物类Animal及其子类DogCat。当我们希望一个方法能够读取不同类型的动物集合,但不修改集合内容时,可以使用? extends T。例如:
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

public class WildcardExample {
    public static void printAnimals(List<? extends Animal> animals) {
        for (Animal animal : animals) {
            System.out.println(animal);
        }
    }
}

这里List<? extends Animal>可以接受List<Dog>List<Cat>,因为DogCat都是Animal的子类。但该方法不能往集合中添加元素(除了null),因为编译器无法确定具体的类型。

  • 应用场景 - 方法参数传递:假设我们有一个获取集合中第一个元素的方法:
public static <T> T getFirst(List<? extends T> list) {
    return list.isEmpty()? null : list.get(0);
}

这个方法可以接受任何类型的集合,只要它是T的子类的集合,并且返回T类型的元素。

2.? super T 的应用场景及解释

  • 应用场景 - 集合操作:还是以动物类为例,当我们希望一个方法能够往集合中添加特定类型及其子类的元素时,可以使用? super T。例如:
public static void addDog(List<? super Dog> dogs) {
    dogs.add(new Dog());
}

这里List<? super Dog>可以接受List<Dog>List<Animal>(因为DogAnimal的子类)。这样就可以往集合中添加Dog对象。

  • 应用场景 - 方法参数传递:假设我们有一个将元素添加到集合的通用方法:
public static <T> void addElement(List<? super T> list, T element) {
    list.add(element);
}

这个方法可以接受任何类型的集合,只要它是T的超类的集合,并且可以将T类型的元素添加到集合中。

3. 区别和使用原则

  • 区别
    • ? extends T表示类型的上界,即可以是TT的子类,主要用于读取数据,因为它保证了集合中的元素类型是T或其子类,但不能安全地添加元素(除了null)。
    • ? super T表示类型的下界,即可以是TT的超类,主要用于写入数据,因为它保证了可以添加T及其子类的元素到集合中,但读取元素时,得到的是Object类型(需要类型转换,除非明确知道具体的超类类型)。
  • 使用原则
    • 当你只需要从集合中读取数据时,使用? extends T
    • 当你只需要往集合中写入数据时,使用? super T
    • 当你既需要读取又需要写入数据时,不要使用通配符,而是使用具体的泛型类型。