java泛型中上下限通配符 extends与super

1. List<? extends Dog>add 操作

首先来看 List<? extends Dog> 的情况,它使用了 上限通配符 extends。由于你使用了 extends Dog,它表示列表的元素类型可能是 Dog 或者 Dog 的某个子类。虽然你能读取列表中的元素,但 你不能安全地添加任何类型的元素,因为你无法确定该列表实际接受哪种具体类型。换句话说,List<? extends Dog> 是一个“只读”的列表,只能从中读取 Dog 或它的子类,但不能随意向其中添加元素。

List<? extends Dog> list = new ArrayList<>();
list.add(new Dog());   // 编译错误:无法添加元素
list.add(new Poodle()); // 编译错误:无法添加元素

Objec object = list.get(0) // 读取元素是合法的

Dog dog = list.get(0); // 读取元素是合法的,但返回类型为 `Object`,这里强制转换

为什么不能添加元素?

  • 你无法知道 List<? extends Dog> 中到底存储的是 Dog 还是它的某个子类(例如 Poodle)。
  • 如果你能够添加元素,那么假设你添加了一个 Cat 对象(假设 CatDog 的兄弟类),编译器无法确保类型的安全性。

总结:List<? extends Dog> 中,你无法安全地添加任何元素,因为它可能存储的是 Dog 的子类,无法保证添加的元素类型与列表中的元素兼容。

2. List<? super Dog>add 操作

接下来看 List<? super Dog> 的情况,它使用了 下限通配符 super。这里,? super Dog 意味着该列表的元素类型可以是 Dog 或者 Dog 的父类(如 AnimalObject)。对于 add 操作,它是安全的,因为你明确知道你可以添加 Dog 类型及其子类不是父类,而是子类)(例如 Poodle)。

List<? super Dog> list = new ArrayList<>();
list.add(new Dog());   // 可以安全地添加
list.add(new Poodle()); // 可以安全地添加
list.add(new Animal()); // 错误,只能添加Dog以及子类

Objec object = list.get(0) // 读取元素是合法的

Dog dog = list.get(0); // 读取元素是合法的,但返回类型为 `Object`,这里强制转换

为什么可以添加元素?

  • 你可以向 List<? super Dog> 中添加 Dog 或其子类的元素,因为无论它的实际类型是什么(DogAnimalObject),你都可以安全地假定 Dog 或其子类是符合要求的。
  • 这里的关键是 super Dog 指定了下限,意味着列表接受 Dog 及其任何子类作为元素,因此可以添加这些类型。

3. 区别总结:

操作List<? extends Dog>List<? super Dog>
读取(get)可以读取,类型是 Dog 或其子类,但会返回 Object可以读取,但类型不确定,所以也需要当做 Object 类型处理
添加(add)不能添加任何元素,因为你不能确定具体类型可以添加 Dog 或其子类的元素,但不能添加超出 Dog 的类型
安全性安全地读取,但不能安全地添加元素可以安全地添加 Dog 或其子类的元素,但读取时会丧失类型信息

4.如何添加元素?

不能通过add,不过可以通过换引用方式赋值,例如:

List<Integer> intList = new ArrayList<>(Arrays.asList(1, 2, 3)); // 原始List有元素
List<? extends Number> numbers = intList; // 通过通配符引用
System.out.println(numbers.get(0)); // 输出1 ✅

List<Object> objList = new ArrayList<>(Arrays.asList("A", "B")); // 原始List有元素
List<? super Number> sink = objList; // 通配符引用
sink.add(3.14); // ✅ 可以写入Number的子类
System.out.println(objList); // 输出 [A, B, 3.14]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值