泛型中 的区别


?T 是什么?

? 是通配符,T 是类型变量。根据字面意思,<? extends T> 表示 任何继承自类型 T 的类型<? super T> 表示 任何是类型 T 的超类的类型

上界和下界

泛型的关系-extends.png

下面代码就是 上界通配符(Upper Bounds Wildcards)
Plate<? extends Fruit> 

它的表意是,一个能放 Fruit 及其子类的盘子。


泛型的关系-super.jpg

下面代码就是 下界通配符(Lower Bounds Wildcards)
Plate<? super Fruit> 

它的表意是,一个能放 Fruit 及其父类的盘子。

PECS 原则

1. <? extends T> 不能往里存,只能往外取

class Plate<T> { private T item; public Plate(T t) { item = t; } public void set(T t) { item = t; } public T get() { return item; } } 

往里存的意思就是,不能对泛型 T 类型所代表的成员变量 item 进行赋值(赋值成一种特定类型)。往外取的意思就是对泛型 T 类型所代表的成员变量 'item' 进行进行类型转换(转换成一种特定类型)。

Plate<? extends Fruit> p = new Plate<Apple>(new Apple()); // 不能被存入任何元素 p.set(new Fruit()); // exception p.set(new Apple()); // exception // 取出来的东西只能放在 Fruit 或它的基类里 Fruit fruit = p.get(); Object object = p.get(); Apple apple = p.get(); 
  • 注意以上代码,只有在构造函数中可以对 T 类型的 item 进行赋值,通过 set 方法进行赋值是不行的。原因是编译器通过 <? extends Fruit> 只知道 Plate 接受的是 Fruit 及其子类,但是具体是哪个不能确定。但是从写法上,我们在构造时已经显式地指明了 Plate 的类型是 Apple,为什么编译器还不知道呢?这是因为 JVM 在设计初期就没有考虑过泛型,因此对于 JVM 编译成的字节码来说,也没有泛型的概念,JVM 会使用一个占位符 CAP#1 来表示 Plate 接受一个 Fruit 或子类。所以无论想往 Plate 插入任何类型都不可以(因为你不能赋值一个 CAP#1 类型)
  • 但是,将 <? extends Fruit> 替换为一个具体的类型,set 方法就是生效的。这是因为编译器已经知道 Plate 只会接受一个确定类型的水果 Apple
Plate<Apple> applePlate = new Plate<>(new Apple()); applePlate.set(new Apple()); Apple apple = applePlate.get(); applePlate.set(new GreenApple()); 
  • 但是下面的写法是不被接受的。因为泛型 T 是一个类型变量,它不能被用于表达式中。
Plate<T extends Fruit> p = new Plate<>(new Apple()); 
  • 如果写 Plate<?>,则表示 Plate 中放的是任意类型,因此什么也存不进去,可以往外取 Object
Plate<?> anyPlate = new Plate<>(new Apple()); Object o = anyPlate.get(); 

其实存不进去的根本原因是因为,Java 类没有一个共同的子类,但是却有一个共同的父类 Object。所以永远可以向上转型取数据,却不能向下转型存数据。

2. 下界 <? super Fruit> 不影响往里存,但是往外取只能放在 Object

使用下界 <? super Fruit> 的意思是,Plate 中存放的是任意 Fruit 的基类,但是不确定是哪一个。因此往里放 Fruit 以及其子类一定是可以的(因为这些类一定是 <? super Fruit> 的子类)。但是往外取时就只能是 Object,因为编译器不知道你存的是 Fruit 还是 MeatFruitMeat 就只有一个共同父类,那就是 Object。因此往外取 Object 一定是对的。

3. PECS(Producer Extends Consumer Super)

3.1 Producer Extends 你写的类是主要作为生产者向外提供数据,那么就用 extends
3.2 Consumer Super 你写的类是主要作为消费者,需要吃进数据,那么就用 super


作者:你可记得叫安可
链接:https://www.jianshu.com/p/0808c0029b2d
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM