java敏捷开发模式面试题,一文了解PECS(1)

A 在使用下界通配符时,无法使用get方法获取Object以外的元素,或者需要向下转型,但是可能出现ClassCastException的异常。

原因分析:上界通配符,在使用get方法的时候,此时类型没有明确还是问号?我们只能明确其最大父类或者接口时,我们才能接收,但是我们只能明白<? super E>作为形参时例如List<? super E>时,只能明确Object是最大父类,其他的一概不知,所以只能Object o = list.get(0)。

B 可以使用集合的add方法添加E或者E的子类。

原因分析:上界通配符已经解释很清楚了,add方法添加元素时,?类型不确定就要明确该?类型的最小子类,只要比可能存在的最小子类或者子接口小的任意引用数据类型的对象,我们都可以将其添加,而下界通配符<? super E>当作形参时例如List<? super E>,此时E就是最小子类,此时add方法可以添加E或者E的父类或者接口。

2、对PECS原则的解读


  1. 什么是PECS原则?

PECS是Producer Extends Consumer Super的递归缩写,是Java中使用泛型通配符的原则。

  1. 阿里巴巴的通配符使用规约

泛型通配符<? extends T>来接收返回的数据,此写法的泛型集合不能使用 add 方法,而 < ? super T> 不能使用 get 方法,做为接口调用赋值时易出错。

说明:扩展说一下 PECS 原则:第一、频繁往外读取内容的,适合用<? extends E>。第二、经常往里插入的,适合用<? super E> 。

  1. 对PECS原则的简单解读

字面意思是生产者要被继承要被当作上界通配符<? extends E>的上界E,消费者要继承其他类要被当成下界通配符<? super E>的下界E,再借助下阿里巴巴的泛型开发规约去理解下,应该就是当这个被传入的类型需要进行很多get操作获取数据的话,那么请使用上界通配符这时这个上界就如同生产者一样,因为它能被不断get到,而当需要不断进行add方法添加数据的话,请使用下界通配符这时这个下界就如同消费者一样,因为它不断地索取,因为我们在不断地add元素给它。

三、代码演示

=====================================================================

import java.util.*;

/**

  • @author 步尔斯特

  • @date 2022-01-25 上午11:09

**/

public class ListTest {

public static void main(String[] args) {

//最小子类

Student student = new Student();

// 多态体现

List animals = new ArrayList<>();

animals.add(student);

List person = new ArrayList<>();

person.add(student);

List students = new ArrayList<>();

students.add(student);

// List<?> 无界通配符

// List<? extends Person> 上界通配符 ?表示Person的子类

// List<? super Person> 下界通配符 ?表示Person的父类

// 调用上界通配符接口保存信息,接口入参为 List<? extends Person>,只能传入List或者List

saveExtendsList(person);

saveExtendsList(students);

// saveExtendsList(animals);//不满足,编译器报错

// 调用下界通配符接口保存信息,接口入参为 List<? super Person>,只能传入List或者List

saveSuperList(person);

saveSuperList(animals);

// saveSuperList(students);//不满足,编译器报错

// 调用别人提供的接口,获取集合信息,不清楚提供方到底返回的是哪个集合,List 还是 List ?

List<? extends Person> extendList = getExtends();

// 调用get会返回上边界父类对象,可以用父类方法操作子类

Person p = extendList.get(0);

// Student s = extendList.get(0);//不满足,编译器报错,编译器表示,老色龙后代五花八样,谁知道你是啥样的人

// 下面三行全报错,按理说应该可以添加student对象,从当前类看只有animal,student,person三个类,如果还有别的呢,

// 比如学生下面还有两个同级子类,高中生和小学生,别人提供的接口返回的是高中生,然后添加了小学生,编译器表示这个我懵逼,我得报错

// extendList.add(new Student());//不满足,编译器报错

// extendList.add(new Person());//不满足,编译器报错

// extendList.add(new Animal());//不满足,编译器报错

// 那有没有啥办法让编译器不懵逼呢?

// 如果您很确定返回的是某个类的数据,强转

List studentList = (List) getExtends();

studentList.add(new Student());

List personList = (List) getExtends();

personList.add(new Student());

List animalList = (List) getExtends();

animalList.add(new Student());

// 若果您看懂了上面,下面soEasy了

// 调用别人接口获取数据,只知道数据是person或者person父类的集合

List<? super Person> aSuper = getSuper();

// 所以用get获取数据,编译器表示老子怎么知道是你哪个老子,压根不晓得你的老子是啥,万一是禽兽呢,我只能object呀,你自己去判断

Object object1 = aSuper.get(0);

// 同样如果知道是哪个,强转

Animal dd = (Animal) aSuper.get(0);

// add方法,编译器表示,你的父类肯定是你儿子孙子的父类,多态支持我这么搞

aSuper.add(new Person());

aSuper.add(new Student());

}

/**

  • 接口:保存信息

  • 此处,必须传入person类或者父类集合

  • @param list 下界通配符 ?表示Person的父类

*/

public static void saveSuperList(List<? super Person> list) {

}

/**

  • 接口:保存信息

  • 此处,必须传入person类或者子类集合

  • @param list ? extends Person 上界通配符

*/

public static void saveExtendsList(List<? extends Person> list) {

}

public static List<? super Person> getSuper() {

return new ArrayList<>();

}

public static List<? extends Person> getExtends() {

return new ArrayList<>();

}

static class Animal {

}

static class Person extends Animal {

}

static class Student extends Person {

}
}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

这份文档从构建一个键值数据库的关键架构入手,不仅带你建立起全局观,还帮你迅速抓住核心主线。除此之外,还会具体讲解数据结构、线程模型、网络框架、持久化、主从同步和切片集群等,帮你搞懂底层原理。相信这对于所有层次的Redis使用者都是一份非常完美的教程了。

image

整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断!!!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
外,还会具体讲解数据结构、线程模型、网络框架、持久化、主从同步和切片集群等,帮你搞懂底层原理。相信这对于所有层次的Redis使用者都是一份非常完美的教程了。

[外链图片转存中…(img-sil2qYIR-1713300255633)]

整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断!!!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 11
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值