泛型函数 android,泛型 · Android 面试文档 · 看云

[TOC]

## 泛型类

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20200224234745.png)

## 泛型接口

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20200224234848.png)

## 泛型方法

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20200224235032.png)

## 泛型边界

使用 extend 边界符来界定,限制泛型的类型,和下面的通配符不一样

如上面泛型方法所示,使用了 extend 关键字

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20200224235032.png)

这里是在泛型方法中的应用,其实可以用到泛型类或者泛型接口上

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20200224235533.png)

## Super 和 extend 通配符

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20200225001445.png)

定义了

动物类 Animal

动物类的子类 Fish 鱼

鱼的子类 Curcian 鲫鱼

动物类的子类 Dog

### 先来看 super 通配符

``` java

// 鱼的集合

List super Fish> list = new ArrayList<>();

list.add(new Fish());

list.add(new Crucian());

```

super Fish> 规定了泛型是 Fish 或者 Fish 的父类。

这个时候,我们只能知道list 是只能存放 Fish 或者 Fish 父类的容器,这个时候如果往里面放 Fish 或者是 Fish 的子类,可以放心放进去。但是 Fish 的父类就不能放进去了,因为编译器不知道会放入Fish 的哪个父类,所以编译器直接禁止用 super 通配符加入超类对象。

同时,编译器只知道list 存的是 Fish 或者Fish 的超类,并不知道存储的是哪个超类,所以 用 super 修饰的泛型列表是允许访问的。

也就是只允许加入 Fish 或者 Fish 的子类对象(多态)。不允许加入Fish 的父类。并且不允许对 list 进行访问

### 再来看 extend 通配符

~~~

// 鱼的集合

List extends Fish> list2 = new ArrayList<>();

// 不能加入

list2.add(new Fish());

list2.add(new Crucian());

// 可以访问

System.out.println(list2.get(0).getName());

System.out.println(list2.get(2).isYouYong());

~~~

super Fish> 规定了泛型是 Fish 或者 Fish 的子类。

这个时候list2 里面存放的只能是 Fish 或者 Fish 的子类,如果我们往里面加入Fish 或者 Fish 的子类,编译器并不知道我们加入是是什么 Fish 的子类,所以编辑器禁止向 extend 修饰的列表加入任何子类,同样的,也不允许加入Fish 本身,事实上不能往被 ? extend Fish 修饰的泛型加入任何值、

但是编译器知道该 list2 中存放的是 Fish 或者 Fish 的子类,所以可以对 list2 进行访问。

## PECS 法则

P - Producor 生产者

E - extends

C - Consumer 消费者

S - super

即:

1. 如果要从集合中读取类型T的数据,并且不能写入,可以使用 ? extends 通配符;(Producer Extends)

2. 如果要从集合中写入类型T的数据,并且不需要读取,可以使用 ? super 通配符;(Consumer Super)

如果既要存又要取,那么就不要使用任何通配符。

## 泛型擦除

**泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除**。

比如

~~~

List s1 = new ArrayList<>();

List i1 = new ArrayList<>();

System.out.println(s1.getClass() == i1.getClass());

~~~

返回的结果是 true,所以在运行的时候List 后面的泛型就被擦除了,所以就会出现上面 s1 == i1 的情况

## 下面的可以忽略

super 主要用来添加数据的。

使用 super 修饰的数据,可以添加子类,但是由于不知道是添加的哪个子类,但是访问的时候可能会出问题

extend 主要用来访问数据的

使用 extend 修饰的数据,不可以添加数据,但是可以访问数据

### 通配符 ?

PECS原则:

使用 super 通配符,用来添加数据,只要是属于限定符后面 类的子类都可以添加。

使用 extend 通配符,用来访问数据,因为接收的数据,都可以保证是限定符后面的类的子类,可以任意的访问限定度后面类中的方法。

* 对于`List super Integer> l1`:

* 正确的理解:`? super Integer`限定的是泛型参数. 令 l1 的泛型参数是 T, 则 T 是 Integer 或 Integer 的父类, 因此 Integer 或 Integer 的子类的对象就可以添加到 l1 中.

* 错误的理解:~? super Integer限定的是插入的元素的类型, 因此只要是 Integer 或 Integer 的父类的对象都可以插入 l1 中~

* 对于`List extends Integer> l2`:

* 正确的理解:`? extends Integer`限定的是泛型参数. 令 l2 的泛型参数是 T, 则 T 是 Integer 或 Integer 的子类, 进而我们就不能找到一个类 X, 使得 X 是泛型参数 T 的子类, 因此我们就不可以向 l2 中添加元素. 不过由于我们知道了泛型参数 T 是 Integer 或 Integer 的子类这一点, 因此我们就可以从 l2 中读取到元素(取到的元素类型是 Integer 或 Integer 的子类), 并可以存放到 Integer 中.

* 错误的理解:~? extends Integer 限定的是插入元素的类型, 因此只要是 Integer 或 Integer 的子类的对象都可以插入 l2 中~

## 泛型擦除

**泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除**。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值