实用指南:10分钟理解泛型的通配符(extends, super, ?)

news/2025/11/24 10:08:02/文章来源:https://www.cnblogs.com/ljbguanli/p/19262580

实用指南:10分钟理解泛型的通配符(extends, super, ?)

      • 泛型通配符是什么?
      • 三种基本通配符
        • 1. 无边界通配符:`<?>`
        • 2. 上界通配符:`<? extends T>`
        • 3. 下界通配符:`<? super T>`
      • PECS原则:Producer Extends, Consumer Super
      • 实际应用举例
        • 1. 方法参数设计
        • 2. 集合操作工具方法
      • 常见误区和注意事项
        • 1. 通配符不能用于创建对象
        • 2. 通配符不能作为泛型方法的实际类型参数
        • 3. 理解边界的方向
      • 总结

泛型通配符是什么?

在学习Java泛型的过程中,我们经常会遇到三个特殊的符号:?extendssuper。它们组合起来形成的通配符(wildcard)是泛型中最让人头疼的部分,但也是最强大的特性之一。

简单来说,通配符就是用来表示"某种不确定的类型"。就像我们在填表时遇到的"其他"选项一样,当具体类型不重要或者无法确定时,就可以用通配符来代替。

三种基本通配符

1. 无边界通配符:<?>

这是最简单的通配符形式。<?> 表示"某个未知的类型"。

List<?> list = new ArrayList<String>();  // 可以指向任何类型的Listlist = new ArrayList<Integer>();         // 也可以重新赋值为其他类型

使用 <?> 的限制是:你不能向其中添加除了 null 以外的任何对象,因为你不知道实际的类型是什么。

List<?> list = new ArrayList<String>();list.add(null);     // 这个可以// list.add("hello");  // 编译错误!
2. 上界通配符:<? extends T>

这种写法表示"某个继承自 T 的类型",或者说"某种 T 类型或其子类型"。

List<? extends Number> numbers = new ArrayList<Integer>();  // Integer是Number的子类numbers = new ArrayList<Double>();   // Double也是Number的子类

为什么要叫"上界"?因为 [Number]是上限,实际类型必须是 [Number]或其子类。

使用上界通配符时的限制:

  • 可以安全地从中读取数据(因为读到的肯定能当成 [Number]处理)
  • 不能向其中写入数据(因为不知道具体是哪种子类型)
List<? extends Number> numbers = new ArrayList<Integer>();Number num = numbers.get(0);  // 可以读取,肯定是Number类型// numbers.add(new Integer(1));  // 编译错误!
3. 下界通配符:<? super T>

这种写法表示"某个 T 的父类型",也就是"某种 T 类型或其父类型"。

List<? super Integer> integers = new ArrayList<Number>();   // Number是Integer的父类integers = new ArrayList<Object>();  // Object是所有类的父类

这里 Integer 是下限,实际类型必须是 Integer 或其父类。

使用下界通配符时的特点:

  • 可以安全地向其中写入T 类型的数据
  • 从中读取数据时只能当作 Object 处理(因为不知道具体是哪个父类)
List<? super Integer> integers = new ArrayList<Number>();integers.add(new Integer(1));    // 可以写入Integerintegers.add(42);                // 自动装箱也行// Integer num = integers.get(0);   // 错误!只能当Object用Object obj = integers.get(0);    // 正确!

PECS原则:Producer Extends, Consumer Super

这是使用泛型通配符的重要口诀:

  • Producer Extends:如果你只是从容器中获取数据(生产者),使用 <? extends T>
  • Consumer Super:如果你只是向容器中放入数据(消费者),使用 <? super T>

让我们通过一个具体的例子来理解:

public static void copy(List<? extends Number> source,List<? super Number> destination) {for (Number num : source) {        // source是生产者,用extendsdestination.add(num);          // destination是消费者,用super}}

在这个例子中:

  • [source]列表我们只从中读取数据,所以用 <? extends Number>
  • [destination]列表我们只向其中写入数据,所以用 <? super Number>

实际应用举例

1. 方法参数设计
// 错误的设计:太严格了
public static void printList(List<Object> list) {for (Object item : list) {System.out.println(item);}}// 正确的设计:灵活得多public static void printList(List<?> list) {for (Object item : list) {System.out.println(item);}}// 使用List<String> strings = Arrays.asList("a", "b", "c");List<Integer> integers = Arrays.asList(1, 2, 3);printList(strings);    // 现在可以用了printList(integers);   // 这个也可以
2. 集合操作工具方法
// 向一个列表中添加另一个列表的所有元素
public static <T> void addAll(List<? super T> dest, List<? extends T> src) {for (T item : src) {dest.add(item);}}// 使用List<Object> objects = new ArrayList<>();List<String> strings = Arrays.asList("hello", "world");addAll(objects, strings);  // 可以把String列表加到Object列表中

常见误区和注意事项

1. 通配符不能用于创建对象
// 错误!
// List<?> list = new ArrayList<?>();
// 正确的做法
List<?> list = new ArrayList<String>();
2. 通配符不能作为泛型方法的实际类型参数
public static <T> void method(List<T> list) {// ...}// 错误!// method(new ArrayList<?>());// 正确的做法List<String> stringList = new ArrayList<>();method(stringList);
3. 理解边界的方向

很多人容易搞混 extendssuper 的方向:

// extends: 设置上界(上限)
List<? extends Number>  // 实际类型是Number或其子类// super: 设置下界(下限)  List<? super Number>    // 实际类型是Number或其父类

总结

泛型通配符的核心思想是为了增加代码的灵活性:

  1. <?>:完全不知道类型,只能读取为 Object,基本不能写入
  2. <? extends T>:知道是 T 或其子类,可以安全读取为 T,不能写入
  3. <? super T>:知道是 T 或其父类,可以安全写入 T,读取只能当 Object

记住PECS原则,在设计API时合理使用通配符,可以让代码既安全又灵活。刚开始接触时会觉得复杂,但多练习几次就很容易掌握了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/974505.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年小型激光打标机生产厂家权威推荐榜单:光纤激光打标机/金属激光打标机/紫外激光打标机源头厂家精选

在精密加工、电子元件、医疗器械等行业,小型激光打标机以其精度高、适用性强的特点,正成为企业实现产品标识追溯和品牌价值提升的关键设备。 小型激光打标机技术日益成熟,凭借其占地面积小、能耗低、集成度高的优势…

实用指南:内容创作者的新赛道:如何通过ChatGPT SEO获取下一代流量

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

webpack plugin 原理

基础问答 问:什么是 Webpack Plugin?它的核心作用是什么? 答:Webpack Plugin 是 Webpack 插件系统,本质是一个实现了 apply 方法的 JavaScript 类或函数。Plugin 通过 Webpack 提供的构建生命周期的回调钩子介入构…

.net后端开发学习路线

路线图总览阶段一:编程与C#基础 - 打好根基阶段二:Web开发核心技术 - 打开Web世界的大门阶段三:专业方向分化 - 成为后端或前端专家阶段四:进阶与架构 - 从程序员向工程师转变阶段五:拓展与精深 - 成为领域专家阶…

2025年平顶山正规戒网瘾机构权威推荐榜单:戒网瘾/孩子戒网瘾/青少年戒网瘾源头机构精选

在数字化时代背景下,青少年网络成瘾问题日益受到社会关注。据2025年教育部门统计数据显示,我国青少年网络依赖现象发生率已达18.6%,专业干预服务的市场需求持续增长。随着家庭教育理念的升级和专业服务的规范化发展…

倍增并查集

简介倍增并查集更新日志 2025/11/24:开工。概念 类似于两个区间内,各个位置一一对应连边的问题,就可以考虑使用倍增并查集解决。比如说,QOJ9904。 思路 以例题为例,转化后就是相当于给一个区间每对左起第 \(i\) 个…

ASP.NET Core Web API 为 Swagger 创建多个分组文档

ASP.NET Core Web API 为 Swagger 创建多个分组文档的教程,我们主要可以通过 `AddSwaggerGen`、`SwaggerDoc`、`UseSwaggerUI`、`SwaggerEndpoint`、`ApiExplorerSettingsAttribute` 这几个 API 进行相关的编辑,实现…

2025年开式冷却塔生产厂家权威推荐榜单:闭式冷却塔/大型冷却塔/空冷器源头厂家精选

在工业生产过程中,冷却系统是保障设备稳定运行的关键环节。开式冷却塔作为工业冷却系统的重要组成部分,其性能直接影响生产效率和能源消耗。根据行业数据显示,开式冷却塔在工业领域的应用占比达到67%,其中电力、化…

Java中数组常见操作

在力扣算法题中,Java对数组的常见操作及其复杂度: 1. 排序操作 Arrays.sort(nums); // 时间复杂度: O(nlogn) Arrays.sort(nums, 1, 4); // 时间复杂度: O(klogk), k为排序范围大小/…

2025年树脂拉链制造企业权威推荐榜单:尼龙拉链/金属拉链/隐形拉链源头厂家精选

在服装、箱包和户外用品等行业中,树脂拉链凭借其轻便、耐磨和设计多样化的特点,成为众多品牌的首选辅料。面对市场上众多的生产厂商,如何选择可靠且专业的合作伙伴成为采购决策的关键。为此,我们基于企业综合实力、…

小企业OKR实施的组织变革与本土化路径

小企业OKR实施的组织变革与本土化路径I. 导论:将OKR实施界定为一次深刻的组织变革目标与关键结果(Objectives and Key Results, OKR)框架,一种源自彼得德鲁克(Peter Drucker)的目标管理(MBO)思想,并在英特尔(…

二、使用Spring AI实现简单聊天功能(实现角色预设、流式和非流式响应)

二、使用Spring AI实现简单聊天功能(实现角色预设、流式和非流式响应) ================================================================================== ==================================================…

安装一个为RK3588S优化的、启用了OpenCL (GPU加速) 和 NEON (CPU加速) 的OpenCV 4.10版本。

第1步:环境准备与系统加固 这是最重要的一步,为后续所有操作打下稳定基础。 锁定Mali GPU驱动 (防止“变砖”):新烧录的系统,第一件事就是锁定厂商提供的GPU驱动,防止apt upgrade将其覆盖导致GPU硬件加速失效(退…

网页版RStudio跑Harmony总报错?可能是这个原因导致的

进行单细胞测序数据分析,Harmony是目前最常用的去批次工具之一,但在RStudio(特别是网页版/Server版)环境中配合Seurat使用时,经常会遇到关于对象命名的报错。library(harmony) library(Seurat)# samples 是已经经过…

递归算法如何分析复杂度?

递归算法复杂度分析 递归是算法设计中的重要技术,能将复杂问题分解为相似子问题。然而,递归算法的性能分析往往比迭代算法复杂。本文系统介绍递归算法时间与空间复杂度的分析方法,并通过实例帮助你掌握这一关键技能…

常用的文件摆渡系统:让数据安全高效跨越网络界限

在企业数字化运营中,网络隔离是保障数据安全的重要手段,但研发资料下发、分支机构协同、客户文件交互等场景,仍需安全可控的跨网数据传输,“文件摆渡系统”由此成为关键工具。常用的文件摆渡系统是指能在不打破网络…

2025苏州最好的留学机构是哪家公司

2025苏州最好的留学机构是哪家公司一、2025年苏州留学机构选择指南:五大核心问题解析作为从事国际教育规划工作已逾十年的专业人士,我常被苏州家长和学生问及:在2025年的留学市场中,到底哪家机构真正值得信赖?通过…

2025深圳英国留学中介有哪些机构

2025深圳英国留学中介有哪些机构一、深圳英国留学中介怎么选?看看这些常见问题作为一名从事国际教育规划工作超过十二年的专业人士,我经常被家长和学生们问及:深圳英国留学中介哪家更让人放心?申请英国研究生阶段,…

2025南昌留学机构哪家好

2025南昌留学机构哪家好作为从事12年国际教育规划师的我,经常被学生和家长问起:2025年南昌留学机构哪家好?在选择留学中介时,大家总会有各种疑问。比如,南昌本地的留学机构哪家更合适自己的背景?哪个机构的服务更…

2025广州哪里有好的留学机构

2025广州哪里有好的留学机构一、2025年广州留学机构如何选择?这五类问题帮你理清思路作为一位拥有八年经验的国际教育规划师,我每天都会接触到大量广州学生和家长的咨询。大家最常问的问题往往非常具体:广州本地的留…