泛型(Generic) <? extends T>,<? super T>
通配符边界引入背景
使用泛型的过程中,经常出现一种很别扭的情况。我们有 Fruit 类,和它的派生类 Apple 类。
class Fruit {}
class Apple extends Fruit {}
然后有一个最简单的容器:Plate 类。盘子里可以放一个泛型的 “东西”.
class Plate<T> {private T item;public Plate(T t) {item = t;}public void set(T t) {item = t;}public T get() {return item;}}
| 代码 | 我们想要表达的意思 | 实际效果 |
|---|---|---|
Plate<Apple> p2 = new Plate<Apple> (new Apple()); | 定义一个"苹果盘子" 装 苹果 | √ |
Plate<Fruit> p = new Plate<Apple> (new Apple()); | 定义一个"水果盘子",逻辑上水果盘子当然可以装苹果。 | error: incompatible types: Plate<Apple> cannot be converted to Plate<Fruit> |
实际上,编译器脑袋里认定的逻辑是这样的:
| 认可关系 | 不认可关系 |
|---|---|
苹果 IS-A 水果 | 装苹果的盘子 NOT-IS-A 装水果的盘子 |
就算容器里装的东西之间有继承关系,但容器之间是没有继承关系的。所以我们不可以把Plate<Apple>的引用传递给Plate<Fruit>。
为了解决这种情况,Sun的大脑袋们就想出了<? extends T>和<? super T>的办法,来让”水果盘子“和”苹果盘子“之间发生关系。
<? extends T> :上界通配符(Upper Bounds Wildcards)☞包括T在内的任何T的子类
意义
Plate<Apple> | Plate<?extends Fruit> |
|---|---|
一个能放苹果的盘子 | 一个能放任意水果的盘子 |
Plate<?extends Fruit> p = new Plate<Apple>(new Apple());可以用“ 苹果盘子”给“水果盘子”赋值了 | Plate<?extends Fruit>是Plate<Fruit>以及Plate<Apple>的基类 |
练习
| level1 | level2 | level3 | level4 |
|---|---|---|---|
class Food{} | class Fruit extends Food{} | class Apple extends Fruit{} | class RedApple extends Apple{} |
class GreenApple extends Apple{} | |||
class Banana extends Fruit{} | |||
class Meat extends Food{} | class Pork extends Meat{} | ||
class Beef extends Meat{} |
Plate<? extends Fruit> 覆盖区域
| level2 | level3 | level4 |
|---|---|---|
class Fruit extends Food{} | class Apple extends Fruit{} | class RedApple extends Apple{} |
class GreenApple extends Apple{} | ||
class Banana extends Fruit{} |
<?superT>:下界通配符(Lower Bounds Wildcards)☞包括T在内的任何T的父类
意义
Plate<Fruit> | Plate<?super Fruit> |
|---|---|
一个能放水果以及一切水果基类的盘子 | |
Plate<?super Fruit>是Plate<Fruit>的基类,但不是Plate<Apple>的基类 |
练习
Plate<?super Fruit>覆盖范围
| level1 | level2 |
|---|---|
class Food{} | class Fruit extends Food{} |
上下界通配符的副作用
边界让Java不同泛型之间的转换更容易了。这样的转换也有一定的副作用。那就是容器的部分功能失效。
还是以刚才的 Plate 为例。我们可以对盘子做两件事,往盘子里set()新东西,以及从盘子里get()东西。
- 上界
<? extends T>不能往里存,只能往外取
Plate<? extends Fruit> p=new Plate<Apple>(new Apple()); //不能存入任何元素
p.set(new Fruit()); //Error
p.set(new Apple()); //ErrorFruit newFruit1=p.get(); //读取出来的东西只能存放在Fruit或它的基类里
Object newFruit2=p.get();Apple newFruit3=p.get(); //Error
原因:
编译器只知道容器内是Fruit或者它的派生类,但具体是什么类型不知道。可能是 Fruit 可能是 Apple 也可能是 Banana,RedApple,GreenApple
编译器在看到后面用 Plate 赋值以后,盘子里没有被标上有 “苹果”。而是标上一个占位符:CAP#1,来表示捕获一个 Fruit 或 Fruit的子类,具体是什么类不知道,代号 CAP#1。然后无论是想往里插入 Apple 或者 Meat 或者 Fruit ,译器都不知道能不能和这个 CAP#1 匹配,所以就都不允许。
- 下界
<? super Fruit>不能往外取,只能往里存
Plate<? super Fruit> p=new Plate<Fruit>(new Fruit());//存入元素正常
p.set(new Fruit());
p.set(new Apple());Object newFruit2=p.get(); //读取出来的东西只能存放在Object类里Apple newFruit3=p.get(); //Error
Fruit newFruit1=p.get(); //Error
原因:
定义的元素是Fruit的基类,那往里存 Fruit及其父类 都可以。但往外读取元素就费劲了,只有 所有类的基类 Object对象 才能装下。但这样的话,元素的类型信息就全部丢失。
相关文章:
泛型(Generic) <? extends T>,<? super T>
通配符边界引入背景 使用泛型的过程中,经常出现一种很别扭的情况。我们有 Fruit 类,和它的派生类 Apple 类。 class Fruit {}class Apple extends Fruit {}然后有一个最简单的容器:Plate 类。盘子里可以放一个泛型的 “东西”. class Plat…...
数云融合|数字化转型中的利器:揭秘云技术的重要角色
数字化转型不仅是一个流行语,而是一项真正能够改变你的业务流程并提高客户参与度的重要战略。要实现数字化转型,必须重新构建业务流程,同时利用AI、物联网、AR、ML、大数据分析等先进技术不断提升客户参与度。这就需要利用云技术提供的强大计…...
Linux篇2
Linux 0. 终端提示信息1. 文件目录结构1.1 文件目录 2. 文本编辑器VI/VIM2.1 VIM编辑器2.1 一般模式2.2 编辑模式2.3 命令模式 3. 网络配置3.1 VMware提供的三种网络连接模式3.2 静态配置网络IP地址3.3 配置主机名3.3.1 修改主机名3.3.2 配置主机名-IP地址映射关系:…...
《微服务实战》 第九章 Gitlab使用
前言 微服务项目,常常需要多人协作完成工作,本章教程是介绍Gitlab使用,使多人协作告别低端的手动拷贝,也告别传统的SVN。 1、下载安装git https://git-scm.com/download/win 1.1、安装好以后,cmd中输入git 2、生成ssh-key ssh-keygen -t rsa -C “zhangsan@163.com”…...
KMP匹配算法
目录 一、暴力匹配法动画演示代码实现 二、KMP算法的概念三、KMP算法的应用题目代码实现 一、暴力匹配法 动画演示 时间复杂度为: O ( m ∗ n ) O(m * n) O(m∗n) 代码实现 #define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std;int…...
ClickHouse笔记: Ubuntu/Centos下的安装, 配置和用户管理
ClickHouse ClickHouse 属于 OLAP 数据库 OLTP 与 OLAP OLTP (On-Line Transaction Processing 联机事务处理), 注重事务处理, 数据记录的性能和安全性OLAP (On-Line Analytical Processing 联机分析处理), 注重数据分析, 重点在查询的性能 一般使用 OLTP 数据库做业务数据…...
网络编程——UDP编程
UDP编程 UDP编程步骤通信流程serverclient 函数接口socketbindrecvfromsendto 举例UDP客户端UDP服务器 UDP编程步骤 在C语言中进行UDP编程的一般步骤如下: (1)包含头文件: 在代码中包含必要的头文件,以便使用UDP编程所…...
linux内核篇-进程及其调度
介绍一个程序从源文件到进程执行的过程 1、编译链接(源文件到二进制文件) Linux 下面二进制的程序也要有严格的格式,称为ELF(Executeable and Linkable Format,可执行与可链接格式) ,这个格式可…...
C#开发的OpenRA游戏之基地工程车执行部署命令
C#开发的OpenRA游戏之基地工程车执行部署命令 前面已经分析接收到网络命令后,可以拿到多个命令对象, 通过命令对象进行遍历,最终会在比较部署命令的类里相同,从而执行部署命令。 可见,网络游戏里的对象操作,都是通过网络发送给服务器,再从服务器返回消息来执行对象的动…...
米哈游的春招实习面经,问的很基础
米哈游的春招实习面经,主要考察了java操作系统mysql网络,这四个方面。 面试流程,共1小时,1min自我介绍,20min写题,剩下问题基础知识。 Java String,StringBuilder, StringBuffer区…...
pro如何添加定时任务
Pro v2.4版本开始后台可以开关控制定时任务,那如何添加新的定时任务呢? 第一步:设置定时任务名称及标识; 文件app\controller\admin\v1\system\SystemTimer中task_name()方法 /**定时任务名称及标识 * return mixed */ public fu…...
bgp路由策略
* - valid 有效的, > - best 最佳的 上图中,有*和>,是有效最佳的。而没有*和没有>,是无效的,下一跳不可达 1--64511是公有AS 64512-65534为私有AS //属于哪个大的联盟 AS200 //连着一个子类AS 65002 //和子…...
chatGPT4.0编写性能测试报告
性能测试报告 测试概述 本次性能测试的目的是评估系统在高负载条件下的性能表现,以确保系统能够满足预期的性能需求。测试过程中,我们关注以下性能指标:响应时间、吞吐量、资源利用率(CPU、内存、磁盘、网络)以及错误…...
jpa多线程事务
百度都百度不到jpa多线程的事务回滚,废话少说,就是干, 实现思路(可看可不看,本人也不喜欢罗里吧嗦的,想直接看干货就跳过这里,直接执行代码): jpa本身是不支持多线程事务…...
加密解密软件VMProtect教程(四):准备项目之SDK功能
VMProtect 是保护应用程序代码免遭分析和破解的可靠工具,但只有在正确构建应用程序内保护机制并且没有可能破坏整个保护的典型错误的情况下才能最有效地使用。 SDK 功能可以集成到受保护应用程序的源代码中,以设置受保护区域的边界,以检测调…...
夏令营教育小程序开发功能和优势有哪些?
随着人们生活水平的提高,对于孩子的教育问题也是越来越重视,无论是教育方式还是教育内容上都追求新颖、多样化。在暑假期间,很多家长也希望孩子能够在这个长假期之间参加一些活动,培养孩子兴趣的同时也丰富假期内容,让…...
Cocos CreatorXR 1.2.0 今日发布,正式支持 WebXR ,并开启 MR 之路
去年九月,Cocos CreatorXR v1.0.1 版本支持了 VR 内容创作,成为率先支持 XR 的国产引擎,今年三月,Cocos CreatorXR v1.1.0 版本实现了对 AR 内容开发的支持。在完成基本功能的建设后,更多开发者开始尝试使用 Cocos Cre…...
Linux 使用笔记(本人出品,必属精品)
文章目录 Part.I IntroductionChap.I 快应用Chap.II 课程所学 Part.II 基础知识Chap.X 杂记 Part.I Introduction Linux 是笔者在大四上学期学的,当时授课的刘老师现在还能偶尔见到。但是平时一般用 Windows,有机会接触 Linux 一般是偶尔在服务器上跑跑程…...
【2023 · CANN训练营第一季】初识新一代开发者套件 Atlas 200I DK A2 第二章——安装Atlas 200I DK A2跑通第一个案例
准备相关软件 包括一台PC机(空间大于10g),读卡器,32gsd卡,一根网线。 具体步骤: 开始烧录开发板镜像:将sd卡插入读卡器,将读卡器插入PC机的USB接口,根据相关链接在PC机下载制卡工具…...
concurrenthashmap
SizeCtl的用法 sizeCtl0或容量大小 (二个构造方法) sizeCtl>0(初始化或扩容后)扩容阈值 sizeCtl-1:正在初始化中 sizeCtl<-1:线程扩容中 知道为什么第一个线程扩容时2,后面的其他线程扩容…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
