136. Java 泛型 - 下限通配符

136. Java 泛型 - 下限通配符 (? super T)

在 Java 泛型中,下限通配符 (? super T) 允许指定某个类型的超类,使代码更具灵活性。 本篇将详细介绍下限通配符的概念,并结合示例帮助理解其应用。


1. 什么是下限通配符 (? super T)?

下限通配符 ? super T 表示T 类型或 T 的任意超类,即:

  • List<? super Integer> 可以存储 Integer 及其所有父类 (如 NumberObject)。
  • 但由于类型不确定,读取元素时只能赋值给 Object

下限通配符的语法

java 复制代码
List<? super Integer> list;
  • list 可以接受 List<Integer>List<Number>List<Object>
  • 可以安全地向 list 添加 Integer 类型的元素

2. 为什么使用下限通配符?

下限通配符 ? super T 适用于:

  1. 希望向集合中添加 T 类型的元素T 及其父类)。
  2. 方法的逻辑仅依赖 T 的超类,而不需要具体的 T 子类信息
  3. 泛型方法中,确保集合能接收更广泛的类型范围

3. 示例:使用 ? super Integer 允许添加 Integer

📌 需求:编写一个方法,向 List 中添加 Integer 值,支持 List<Integer>List<Number>List<Object>

✅ 正确示例

java 复制代码
import java.util.List;
import java.util.ArrayList;

public class LowerBoundWildcard {
    public static void addNumbers(List<? super Integer> list) { // ✅ 适用于 Integer 及其超类
        for (int i = 1; i <= 10; i++) {
            list.add(i); // ✅ 安全添加 Integer
        }
    }

    public static void main(String[] args) {
        List<Integer> intList = new ArrayList<>();
        List<Number> numList = new ArrayList<>();
        List<Object> objList = new ArrayList<>();

        addNumbers(intList); // ✅ 可以传入 List<Integer>
        addNumbers(numList); // ✅ 可以传入 List<Number>
        addNumbers(objList); // ✅ 可以传入 List<Object>

        System.out.println(intList); // 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        System.out.println(numList); // 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        System.out.println(objList); // 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    }
}

🔍 解析

  • addNumbers(List<? super Integer>) 可以接受 List<Integer>List<Number>List<Object>
  • 可以安全地向 list 添加 Integer ,因为 Integer 一定是 ? super Integer 允许的类型
  • 无法保证从 list 读取的数据类型 (只能作为 Object 处理)。

4. 为什么 List<? super Integer>List<Integer> 不一样?

在 Java 泛型中:

  1. List<Integer> 仅适用于 Integer 类型 ,无法存储 NumberObject
  2. List<? super Integer> 可以存储 Integer 及其超类 ,如 NumberObject,但无法确定列表存储的具体类型。

❌ 错误示例

java 复制代码
List<? super Integer> list = new ArrayList<Number>();
Number num = list.get(0); // ❌ 编译错误
Integer i = list.get(0); // ❌ 编译错误
Object obj = list.get(0); // ✅ 只能赋值给 Object

🔍 为什么?

  • Java 只保证 list 里的元素是 Integer 的某个超类,但无法确定具体是什么类型。
  • 只能读取为 Object避免类型转换错误

5. 适用场景

适用于"只写"数据的情况 (向列表添加 T 类型数据)。 ✅ 适用于泛型方法,提高灵活性 (使方法接受 T 及其超类)。 ✅ 适用于需要更广泛兼容性的集合 (如 List<Number> 可以接收 Integer)。


6. ? extends T vs ? super T

通配符 适用情况 读取元素 添加元素
? extends T 适用于只读场景(数据读取 ✅ 可以读取为 T ❌ 不能添加元素(除了 null
? super T 适用于只写场景(数据存储 ❌ 只能读取为 Object ✅ 可以添加 T 类型的数据

7. 结论

? super T 表示某个类型 TT 的超类 。 ✅ 适用于"写入数据"场景 ,确保方法能接收 T 及其超类的列表。 ✅ 不能保证读取的数据类型,只能作为 Object 处理 。 ✅ 适用于泛型方法,使代码更加灵活和通用


🎯 记住口诀:

  • ? extends T 适用于"读取"数据 (如 sum(List<? extends Number>))。
  • ? super T 适用于"写入"数据 (如 addNumbers(List<? super Integer>))。
  • 使用 ? super T,让 Java 泛型更灵活,兼容更多类型! 🚀
相关推荐
悟纤3 小时前
当生产环境卡成 PPT:Spring Boot 线程 Dump 捉妖指南 - 第544篇
java·spring boot·后端
学Java的bb4 小时前
JavaWeb-后端Web实战(IOC + DI)
前端
pe7er4 小时前
React Native 多环境配置全攻略:环境变量、iOS Scheme 和 Android Build Variant
前端·react native·react.js
柯北(jvxiao)5 小时前
Vue vs React 多维度剖析: 哪一个更适合大型项目?
前端·vue·react
JefferyXZF5 小时前
Next.js 中间件:掌握请求拦截与处理的核心机制(六)
前端·全栈·next.js
知识分享小能手5 小时前
Vue3 学习教程,从入门到精通,Vue 3 + Tailwind CSS 全面知识点与案例详解(31)
前端·javascript·css·vue.js·学习·typescript·vue3
江影影影5 小时前
Spring Boot 2.6.0+ 循环依赖问题及解决方案
java·spring boot·后端
快乐就是哈哈哈5 小时前
《JSR303 数据校验全攻略:从入门到实战,玩转优雅的参数验证》
后端
石小石Orz5 小时前
React生态蓝图梳理:前端、全栈与跨平台全景指南
前端
快乐就是哈哈哈5 小时前
Linux 部署与管理 Spring Boot 项目保姆级全流程
后端