A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 长沙-小知姐姐 于 2019-1-3 09:31 编辑





1. 基本概念:

1.无边界的通配符:

主要作用就是让泛型能够接受未知类型的数据。

2.固定上边界的通配符:

接受指定类及其子类类型的数据。

3.固定下边界的通配符:

接受指定类及其父类类型的数据。


2. 基本使用方法:


2.1. 无边界的通配符的使用:
我们以在集合List中使用<?>为例:


这种使用List<?>的方式就是父类引用指向子类对象. 注意, 这里的printList方法不能写成public static void printList(List list)的形式,因为,虽然Object是所有引用数据类型的父类,但是List并不是List的父类,所以如果定义成List,那么就只能传List类型进入方法;
有一点我们必须明确, 我们不能对List<?>使用add方法, 仅有一个例外, 就是 add(null). 为什么呢? 因为我们不确定该List的类型, 不知道add什么类型的数据才对, 只有null是所有引用数据类型都具有的元素. 请看下面代码

由于我们根本不知道list会接受到具有什么样的泛型List, 所以除了null之外什么也不能add.还有, \List<?>也不能使用get方法, 只有Object类型是个例外.原因也很简单, 因为我们不知道传入的List是什么泛型的, 所以无法接受得到的get,但是Object是所有数据类型的父类, 所以只有接受他可以, 请看下面代码:


那位说了, 不是有强制类型转换么? 是有, 但是我们不知道会传入什么类型, 比如我们将其强转为String,编译是通过了, 但是如果传入个Integer泛型的List, 一运行还会出错. 那位又说了, 那么保证传入的String类型的数据不就好了么? 那样是没问题了, 但是那还用<?>干嘛呀? 直接List不就行了

2..2 固定上边界的通配符的使用:


我们仍旧以List为例来说明:

注意:List<?extends E>不能使用add方法, 请看如下代码:

原因很简单, 泛型<? extends E>指的是E及其子类, 这里传入的可能是Integer,也可能是Double, 我们在写这个方法时不能确定传入的什么类型的数据, 如果我们调用:

那么我们之前写的add(1.1)就会出错, 反之亦然, 所以除了null之外什么也不能 add. 但是get的时候是可以得到一个Number, 也就是上边界类型的数据的, 因为不管存入什么数据类型都是Number的子类型, 得到这些就是一个父类引用指向子类对象.


2.3. 固定下边界通配符的使用:


这个较前面的两个有点难理解, 首先仍以List为例:


这个原因也是很简单的, 因为我们所传入的类都是Integer的类或其父类, 所传入的数据类型可能是Integer到Object之间的任何类型, 这是无法预料的, 也就无法接收. 唯一能确定的就是Object, 因为所有类型都是其子类型. 使用? super E还有个常见的场景就是Comparator. TreeSet有这么一个构造方法:就是使用Comparator来创建TreeSet, 大家应该都清楚, 那么请看下面的代码:


不知大家有想过没有, 为什么Comparator这里用的是父类Person, 而不是子类 Student. 初学时很容易困惑, ? super E不应该E是子类才对么? 其实, 实现接口时我们所设定的类型参数不是E, 而是?; E是在创建TreeSet时设定的. 如


这里实例化的comparatorTest的泛型就是和(我这么写只是为了说明白). 在实现接口时使用:


那么上面的结果就成了: 和, 显然是错误的.

3. 总结:
我们要记住这么几个使用原则, 有人将其称为PECS(即"Producer Extends, Consumer Super", 网上翻译为"生产者使用extends, 消费者使用super", 我觉得还是不翻译的好). 也有的地方写作"in out"原则, 总的来说就是:

1,in或者producer就是你要读取出数据以供随后使用(想象一下List的 get), 这时使用extends关键字, 固定上边界的通配符. 你可以将该对象当做一个只读对象;

2,out或者consumer就是你要将已有的数据写入对象(想象一下List的 add), 这时使用super关键字, 固定下边界的通配符. 你可以将该对象当做一个只能写入的对象;

3,当你希望in或producer的数据能够使用Object类中的方法访问时, 使用无边界通配符;
4,当你需要一个既能读又能写的对象时, 就不要使用通配符了.


2 个回复

倒序浏览
一个人一座城0.0 来自手机 中级黑马 2018-12-31 11:09:07
沙发
看一看。
回复 使用道具 举报
通配符接触得少,谢啦
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马