【泛型】泛型:泛型擦除、通配符、上下界限定

简介: Java泛型通过类型参数实现代码复用与编译期类型安全。其核心是**类型擦除**(运行时泛型信息被擦除,兼容旧JVM),配合**通配符**(`?`、`? extends T`、`? super T`)解决类型不变性问题,并依**上下界限定**约束类型范围。遵循PECS原则(生产者用extends,消费者用super),兼顾安全与灵活。

泛型:泛型擦除、通配符、上下界限定


一、泛型基础概述

1. 定义

泛型(Generics)是Java 5引入的特性,允许在类、接口和方法中使用类型参数(Type Parameters),将类型明确推迟到使用时才指定,实现“代码复用 + 类型安全”。

2. 核心作用

  • 类型安全:编译期检查类型,避免运行期 ClassCastException
  • 代码复用:一套逻辑支持多种数据类型,无需重复编写。
  • 可读性:类型参数明确了代码的意图,无需注释说明。

二、泛型擦除(Type Erasure)

1. 概念

Java泛型是编译期特性,JVM运行时无泛型概念。编译器会在编译时“擦除”所有泛型信息,将类型参数替换为具体类型(或 Object),保证与旧版JVM兼容。

2. 擦除规则

类型参数情况 擦除后替换为 示例
无界(无 extends Object List<T>List<Object>
有上界(T extends X 上界类型 X List<T extends Number>List<Number>
多个上界(T extends X & Y 第一个上界类型 X T extends Number & ComparableNumber

3. 擦除后的处理

  • 若类型不匹配,编译器会自动插入强制类型转换(如 String s = (String) list.get(0))。
  • 若泛型方法冲突,编译器会生成桥接方法(Bridge Method)保证多态。

4. 影响与限制

  • 无法创建泛型数组(如 new List<String>[5] 非法,因擦除后为 List<Object>[],类型不安全)。
  • 无法获取泛型类型的 Class 对象(如 list.getClass() 仅返回 List.class)。
  • 静态变量/方法无法使用类的泛型参数(静态域在类加载时初始化,此时泛型未实例化)。

5. 代码示例

// 编译前
List<String> list = new ArrayList<>();
list.add("Java");
String s = list.get(0);

// 编译后(擦除结果)
List list = new ArrayList();
list.add("Java");
String s = (String) list.get(0); // 自动插入强转

三、通配符(Wildcard)

1. 概念

通配符 ? 用于表示“未知类型”,解决泛型“类型不变性”导致的灵活性问题(如 List<String> 不是 List<Object> 的子类)。

2. 三种通配符类型

通配符类型 语法 作用 适用场景
无界通配符 List<?> 表示“任意类型的List”,仅能读取 Object 工具类中处理“不关心具体类型”的逻辑
上界通配符(协变) List<? extends T> 表示“T或T的子类的List”,只读不写 生产者场景(从集合读取数据)
下界通配符(逆变) List<? super T> 表示“T或T的父类的List”,只写不读 消费者场景(向集合写入数据)

3. 核心特性

  • 协变(Extends):若 A extends B,则 List<A> 可视为 List<? extends B> 的“子类”(允许向上转型)。
  • 逆变(Super):若 A extends B,则 List<B> 可视为 List<? super A> 的“子类”(允许向下转型)。

四、上下界限定(Bounds)

1. 概念

上下界限定用于约束类型参数的范围,分为“上界限定(extends)”和“下界限定(super)”,可单独用于类/方法的类型参数,也可与通配符结合。

2. 上界限定(extends

语法

  • 类/接口:class MyClass<T extends Number> { ... }
  • 方法:public <T extends Number> void method(T t) { ... }
  • 通配符:List<? extends Number>

作用

  • 限制类型参数必须是T或T的子类,保证类型安全。
  • 可调用T的方法(如 NumberintValue())。

限制

  • 仅能读取,不能写入(因无法确定具体子类类型,写入会破坏类型安全)。

3. 下界限定(super

语法

  • 通配符:List<? super String>(类/方法的类型参数不支持单独用 super 下界,仅能与通配符结合)

作用

  • 限制通配符必须是T或T的父类,允许写入T或T的子类。
  • 读取时仅能得到 Object(因无法确定具体父类类型)。

4. PECS原则(最佳实践)

Producer Extends, Consumer Super

  • 若集合是生产者(提供数据,读取):用 ? extends T
  • 若集合是消费者(接收数据,写入):用 ? super T

五、三者的关系与实际应用

1. 泛型擦除的底层影响

  • 通配符和上下界限定仅在编译期生效,运行时全部擦除为原始类型。
  • 桥接方法、强制类型转换是编译器为弥补擦除损失的“补偿机制”。

2. 实际开发场景

场景 技术选型 示例代码
工具类(不关心具体类型) 无界通配符 List<?> public static void printList(List<?> list) { ... }
读取集合数据(生产者) 上界通配符 ? extends T public static double sum(List<? extends Number> list) { ... }
写入集合数据(消费者) 下界通配符 ? super T public static void addIntegers(List<? super Integer> list) { ... }
限制类型参数范围 类/方法上界 T extends X class NumberContainer<T extends Number> { ... }

六、总结

核心概念 关键作用 核心限制
泛型擦除 兼容旧版JVM,实现编译期安全 运行期无泛型信息,限制数组/静态域等
通配符 解决类型不变性,提升灵活性 无界通配符功能受限,需结合上下界
上下界限定 约束类型范围,平衡安全与灵活 Extends只读,Super只写(PECS)

通过“泛型擦除保证兼容性,通配符+上下界保证灵活性”,Java泛型实现了“安全、复用、灵活”的统一。

相关文章
|
7月前
|
数据库 索引
索引创建的原则
创建索引需遵循六大原则:针对数据量大、查询频繁的表;在常用作查询、排序、分组的字段上建索引;优先选择区分度高或唯一的字段;varchar字段建议使用前缀索引;尽量创建联合索引,高区分度字段前置;避免过多索引,以降低维护成本,提升查询效率。
|
3月前
|
人工智能 Java API
【SpringAIAlibaba新手村系列】(13)Tool Calling 函数工具调用技术
本文详细解析 Spring AI 的 Tool Calling 技术,阐明其如何弥补大模型“会说不会做”的局限。通过 @Tool 注解,开发者可轻松将 Java 方法暴露为 AI 工具。文中深入讲解了 ToolCallbacks.from() 注册工具的原理,以及工具方法在当前 Spring Boot 进程内通过反射动态执行的底层逻辑,强调了模型决策与框架执行的协同过程,为理解 AI 赋能实际操作奠定基础。
1176 0
|
SQL 关系型数据库 数据库
学习分布式事务Seata看这一篇就够了,建议收藏
学习分布式事务Seata看这一篇就够了,建议收藏
25638 2
|
1月前
|
存储 算法 Java
【JVM虚拟机】垃圾回收GC:垃圾收集器:G1:Region分区、Mixed GC、回收流程、适用场景(高频)(附《思维导图》+《面试高频考点清单》)
G1是JDK 9起默认的低延迟垃圾收集器,将堆划分为2048个可动态分配角色的Region,通过Mixed GC优先回收垃圾最多的区域,结合Remembered Set与SATB算法,在大堆(≥4GB)场景下实现可预测停顿(如≤200ms)与高吞吐平衡。
|
1月前
|
算法 Oracle Java
【JVM虚拟机】垃圾回收GC:垃圾收集器:CMS:核心原理、回收流程、优缺点、废弃原因(附《思维导图》+《面试高频考点清单》)
CMS是JDK 1.5推出的首个并发低延迟GC,专注老年代回收,以“最短STW”为目标,适用于Web交互系统。其采用三色标记+增量更新实现并发标记与清除,虽停顿短但存在CPU占用高、内存碎片、并发模式失败等固有缺陷,终被G1取代。
|
1月前
|
存储 缓存 Java
【JVM虚拟机】垃圾回收GC:四种引用类型:强引用、软引用、弱引用、虚引用(附《思维导图》+《面试高频考点清单》)
本文系统梳理JVM四种引用类型:强引用(永不回收)、软引用(内存不足时回收)、弱引用(GC即回收)、虚引用(仅跟踪回收,需配引用队列)。涵盖原理、回收时机、典型场景(如缓存、ThreadLocal、WeakHashMap)及面试高频对比,助你深入理解Java内存管理与防泄漏机制。
|
1月前
|
存储 SQL 安全
【Java并发编程】JMM Java内存模型:原子性、可见性、有序性、happens-before原则(附《思维导图》+《面试高频考点清单》)
Java内存模型(JMM)是Java并发编程的基石,抽象定义主内存与线程工作内存的交互规则,系统解决可见性、原子性、有序性三大核心问题,并通过happens-before、volatile、synchronized等机制保障多线程安全与跨平台一致性。
|
1月前
|
消息中间件 监控 Java
【Java并发编程】Java虚拟线程与平台线程的区别、虚拟线程调度、适用/不适用场景、在Spring Boot中的集成(2026高频)(附《思维导图》+《面试高频考点清单》)
Java虚拟线程是JDK 21正式推出的轻量级并发方案,由JVM用户态调度,单线程仅占几百字节内存,支持百万级并发。它通过“M:N”调度模型与自动挂载/卸载机制,彻底解决传统平台线程在IO密集型场景下的资源瓶颈与阻塞浪费问题,让同步编程轻松承载高并发。
|
1月前
|
设计模式 Java 调度
【Java并发编程】锁机制:AQS抽象队列同步器:核心原理、CLH队列、独占/共享模式、基于AQS实现的组件(CountDownLatch、CyclicBarrier等)(附《思维导图》+《面试高频考点清单》)
AQS(AbstractQueuedSynchronizer)是Java并发包(JUC)的基石框架,基于volatile state状态变量与CLH双向等待队列,通过模板方法模式支持独占/共享同步语义,为ReentrantLock、Semaphore、CountDownLatch等核心组件提供统一底层实现。