泛型中extends和super的区别

在 Java 泛型中,extendssuper 用于限定泛型的上界和下界,它们的核心区别在于:

  • ? extends T 限定 上界(Upper Bound),表示该类型是 TT 的子类。
  • ? super T 限定 下界(Lower Bound),表示该类型是 TT 的父类。

extendssuper 的详细区别

1. ? extends T —— 上界通配符

  • 语法? extends T
  • 含义:泛型类型必须是 T 本身或者 T 的子类。
  • 应用场景:用于只读数据,不能安全地向集合中添加元素(除了 null)。
  • 适用原则"Producer extends"(生产者使用 extends——如果你只需要从泛型对象中读取数据,而不修改它(不向其中添加新元素),使用 extends
示例
class Animal { }
class Dog extends Animal { }
class Cat extends Animal { }

public class Test {
    public static void printAnimals(List<? extends Animal> list) {
        for (Animal a : list) {
            System.out.println(a);
        }
        // list.add(new Animal()); // ❌ 编译错误
        // list.add(new Dog()); // ❌ 编译错误
    }

    public static void main(String[] args) {
        List<Dog> dogs = new ArrayList<>();
        dogs.add(new Dog());
        
        List<Cat> cats = new ArrayList<>();
        cats.add(new Cat());

        printAnimals(dogs); // ✅ 可以传递 List<Dog>
        printAnimals(cats); // ✅ 可以传递 List<Cat>
    }
}

解释:

  • List<? extends Animal> 允许传入 List<Dog>List<Cat>
  • 不能向 list 添加任何元素(除了 null),因为 Java 编译器无法确定 list 具体是哪种 Animal 的子类,可能是 List<Dog>,也可能是 List<Cat>

2. ? super T —— 下界通配符

  • 语法? super T
  • 含义:泛型类型必须是 T 本身或者 T 的父类。
  • 应用场景:用于写入数据,通常用来添加元素,但读取元素时类型只能保证是 Object
  • 适用原则"Consumer super"(消费者使用 super——如果你只需要向泛型对象中写入数据,而不关心读取的数据具体类型,使用 super
示例
class Animal { }
class Dog extends Animal { }
class Cat extends Animal { }

public class Test {
    public static void addDogs(List<? super Dog> list) {
        list.add(new Dog()); // ✅ 可以添加 Dog
        // list.add(new Animal()); // ❌ 编译错误
        // list.add(new Object()); // ❌ 编译错误
    }

    public static void main(String[] args) {
        List<Animal> animals = new ArrayList<>();
        List<Object> objects = new ArrayList<>();

        addDogs(animals); // ✅ 可以传 List<Animal>
        addDogs(objects); // ✅ 可以传 List<Object>
    }
}

解释:

  • List<? super Dog> 允许传入 List<Animal>List<Object>,因为 AnimalObject 都是 Dog 的父类。
  • 只能安全地向 list 添加 DogDog 的子类
  • 读取数据时,返回类型只能是 Object,因为 list 可能是 List<Object>,编译器无法确定存储的具体类型。

extendssuper 的核心区别总结

对比项? extends T? super T
适用方向上界通配符(Upper Bound)下界通配符(Lower Bound)
可传入的类型TT 的子类 (T itself, T's subclasses)TT 的父类 (T itself, T's superclasses)
适合场景只读(生产者 Producer)只写(消费者 Consumer)
能否添加元素不能(除了 null可以添加 TT 的子类
能否读取元素读取时,类型安全(返回 TT 的父类)读取时,只能保证是 Object

如何选择 ? extends? super

  • 如果你需要读取数据,但不写入:用 ? extends T
  • 如果你需要写入数据,但不读取:用 ? super T
  • 如果即要读取又要写入,就不能用通配符,应直接使用 T

经典口诀

  • "Producer extends, consumer super"(生产者使用 extends,消费者使用 super)。
  • "上界安全读取(extends 适合读),下界安全写入(super 适合写)"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EthanMilk

你的鼓励是我创作的最大动力谢谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值