面试官:什么是泛型擦除、泛型上界、泛型下界、PECS原则? 您所在的位置:网站首页 泛型擦除原理 面试官:什么是泛型擦除、泛型上界、泛型下界、PECS原则?

面试官:什么是泛型擦除、泛型上界、泛型下界、PECS原则?

2024-07-10 02:20| 来源: 网络整理| 查看: 265

文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录 博客园版 为您奉上珍贵的学习资源 :

免费赠送 :《尼恩Java面试宝典》 持续更新+ 史上最全 + 面试必备 2000页+ 面试必备 + 大厂必备 +涨薪必备 免费赠送 :《尼恩技术圣经+高并发系列PDF》 ,帮你 实现技术自由,完成职业升级, 薪酬猛涨!加尼恩免费领 免费赠送 经典图书:《Java高并发核心编程(卷1)加强版》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领 免费赠送 经典图书:《Java高并发核心编程(卷2)加强版》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领 免费赠送 经典图书:《Java高并发核心编程(卷3)加强版》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领

免费赠送 资源宝库: Java 必备 百度网盘资源大合集 价值>10000元 加尼恩领取

面试官:什么是泛型擦除、泛型上界、泛型下界、PECS原则? 尼恩说在前面

在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要的面试题:

问题1:什么是PECS原则? 说说具体怎么用?

问题2:什么是 泛型擦除? 说说原理?

问题3:什么是泛型上界? 什么是泛型下界?

最近又有小伙伴在面试美团,遇到了相关的面试题。

很多小伙伴说,自己对什么PECS 原则,可以说一脸懵逼,面试官不满意,面试挂了。

借着此文,尼恩给大家做一下系统化、体系化的梳理,使得大家内力猛增,展示一下雄厚的 “技术肌肉、技术实力”,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提,offer自由”。

当然,这道面试题,以及参考答案,也会收入咱们的 《尼恩Java面试宝典PDF》V162版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。

《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请到公众号【技术自由圈】获取

首先,从Java的泛型说起。

本文目录

目录面试官:什么是泛型擦除、泛型上界、泛型下界、PECS原则?尼恩说在前面本文目录什么是泛型泛型定义:泛型类、泛型接口、泛型方法为啥不用Object做泛型化?泛型的两大好处泛型的上界/ 上界通配符(Upper Bounds Wildcards)上界通配符(Upper Bounds Wildcards)的问题泛型的下界/ 下界通配符(Lower Bounds Wildcards)下界/ 下界通配符(Lower Bounds Wildcards)的问题PECS原则1. Producer Extends 上界生产2. Consumer Super 下界消费,就是消费者使用 “? super T”通配符泛型的类型擦除无界泛型擦除上界擦除下界擦除说在最后:老马识途,有问题找老架构求助技术自由的实现路径:实现你的 架构自由:实现你的 响应式 自由:实现你的 spring cloud 自由:实现你的 linux 自由:实现你的 网络 自由:实现你的 分布式锁 自由:实现你的 王者组件 自由:实现你的 面试题 自由:免费获取11个技术圣经PDF:

什么是泛型

泛型的本质是 类型参数化,解决类型爆炸的问题。

所谓泛型是指将类型参数化,以达到代码复用提高软件开发工作效率的一种数据类型。

比如: 如果我们的代码中存在很多的 食物类型, 继承关系如下

然后我们要定义一个盘子 plate,注意这个盘子除了 装入食物food之外,还可以装其他的比如 小玩具。

为了装不同类型的食物,我们需要定义不同的盘子:

(1) 装水果的盘子 FruitPlate (2) 装肉的盘子 MeatPlate (3) 装苹果的盘子 ApplePlate (4) 装香蕉的盘子 BananaPlate ..... (N) 装云南苹果的盘子 YunnanFruitPlate

这就是盘子类型的 类型爆炸。

如何解决上面的类型爆炸问题呢? 这就要用到泛型。

那么盘子里的东西的类型,我们就用泛型

//盘子里的东西 private T someThing;

从这个例子看到:泛型是一种类型占位符,或称之为类型参数。

如何使用呢?

public static void main(String[] args) { //创建一个装肉的盘子 PlateDemo1 plateDemo1 =new PlateDemo1(new Pork()); //创建一个装水果的盘子 PlateDemo1 plateDemo2 =new PlateDemo1(new Apple()); }

所谓泛型,就是 数据类型 指定为一个参数,在不创建新类的情况下,通过创建变量的时候去确定 数据的具体类型。

也就是说,在创建对象或者调用方法的时候才明确下具体的类型。

泛型定义:泛型类、泛型接口、泛型方法

泛型定义格式:

:指定一种类型的格式,这里的类型可以看做是形参

:指定多种类型的格式,多种类型之间用逗号隔开。定义的时候是泛型形参

这个泛型形参,将来具体调用时候,需要有给定的类型,那个给定的具体的Java类型可以看出是实参。

泛型可以在类、接口、方法中使用,分别称为泛型类、泛型接口、泛型方法。

第一类:泛型类 定义格式:

修饰符 class 类名 { }

上面的例子就是 泛型类

//盘子,可以装 任何东西,包括 食物 其他 class PlateDemo1 { //盘子里的东西 private T someThing; }

第二类:泛型方法

定义格式:

修饰符 返回值类型 方法名(类型 变量名) { }

示例代码:

public void demo(T t) { ... }

第三类:泛型接口

定义格式:

修饰符 interface 接口名 { }

示例代码:

public interface Generic { void demo(T t); }

泛型接口的实现类

public class GenericImpl implements Generic { public void demo(T t) { ... } } 为啥不用Object做泛型化?

没有泛型的情况的下,好像Object也能实现简单的 泛化。

通过定义为类型Object的引用,来实现参数的“任意化”。

比如上面的例子的 泛型类

//盘子,可以装 任何东西,包括 食物 其他 class PlateDemo1 { //盘子里的东西 private T someThing; }

通过定义为类型Object的引用,来实现参数的“任意化”,结果如下

//盘子,可以装 任何东西,包括 食物 其他 class PlateDemo1 { //盘子里的东西 private Object someThing; }

Object实现参数的 “泛型化”、“任意化”带来的缺点是:要做显式的强制类型转换。

参数类型强制转换有一个大大降低代码复用性和扩展性的坏处:

首先,要求开发者对实际参数类型可预知。 其次,不利于未来的 扩展。 泛型的两大好处

而引入泛型后,有如下好处:

1、避免了强制类型转换,提高代码的复用性和扩展性

泛型中,所有的类型转换都是自动和隐式的,不需要强制类型转换,可以提高代码的重用率,再加上明确的类型信息,代码的可读性也会更好。

2、把运行时期的问题提前到了编译期,编译时的类型检查,使程序更加健壮

使用普通的Object泛化,对于强制类型转换错误的情况,编译期不会提示错误,在运行的时候才出现异常,这是一个安全隐患。

泛型的好处是在编译期检查类型安全,并能捕捉类型不匹配的错误,避免运行时抛出类型转化异常ClassCastException,将运行时错误提前到编译时错误,消除安全隐患。

正是由于以上两点原因,泛型得到了广泛的应用。

比如Java中,所有的标准集合接口都是泛型化的:Collection、List、Set 和 Map。

泛型的上界/ 上界通配符(Upper Bounds Wildcards)

现在我定义一个“水果盘子”,用来装苹果, 逻辑上水果盘子当然可以装苹果。

那么,一个“装苹果的盘子”,能转换成一个“装水果的盘子”吗?

看下面的例子

那么,一个“装苹果的盘子”,能转换成一个“装水果的盘子”吗? 答案是不行的。

编译器 的逻辑是这样的:

苹果 is-a 水果 装苹果的盘子 not is-a 装水果的盘子

也就是说:就算 苹果 is-a 水果,但容器之间是没有继承关系的。

怎么办?这里用到了 泛型上界。 泛型上界是这么定义的:

表示泛型实参类型的上界是“基类B”,

换句话说,泛型实参的类型,可能是“基类B” 或者是“基类B”的子类;

修改之后的例子如下,使用 泛型上界通配符(Upper Bounds Wildcards)后,编译器就不报错误了:

使用(Upper Bounds Wildcards)通配符作为泛型实参,所定义 PlateDemo1 引用,可以 覆盖下图中方框内部的所有子类的 泛型对象。

表示类型的上界,参数化类型可能是T 或者是 T的子类;

PlateDemo1 引用,可以 覆盖下图中方框内部的所有子类的 泛型对象,编译器都不报错,下面的代码如下:

为啥 叫做 上界,而不叫下届? 原因是: 这个通配符,定义了实参的类型上限 为 Fruit,具体如下图:

上界通配符(Upper Bounds Wildcards)的问题

上界通配符(Upper Bounds Wildcards)的作用,实现了 子类泛型对象 到 父类Java泛型对象之间的引用转换。

但是,这样的引用转换也有一定的副作用。

具体如下:

通过例子可以看到:

(1)往基类盘子,set( ) 任何对象,都 失效了

(2)从基类盘子,get ( ) 对象的引用,返回 类型是上界对象, 这个还是 可以的

简单来说: 上界



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有