{"name":"泛型","id":"编程语言-JAVA-高级-泛型","content":"# Java 泛型\n\n## 一、泛型的本质\n\n### 1. 泛型要解决的根本问题\n\n在没有泛型的时代，Java 集合只能以 `Object` 为通用载体：\n\n```java\nList list = new ArrayList();\nlist.add(\"hello\");\nInteger i = (Integer) list.get(0); // 运行时异常\n```\n\n问题的本质是：\n\n> **类型信息丢失 + 类型检查延后**\n\n错误只能在运行时暴露，而不是在编译期被发现。\n\n---\n\n### 2. 泛型的核心思想\n\n**泛型的本质：类型参数化（Parameterized Type）**\n\n泛型不是一种新功能，而是对类型系统的扩展：\n\n* 让“类型”像“参数”一样参与抽象\n* 把类型检查从运行时提前到编译时\n* 在不牺牲复用性的前提下保证类型安全\n\n---\n\n### 3. 泛型带来的核心价值\n\n泛型的价值可以归纳为三个维度：\n\n| 维度   | 本质            |\n| ---- | ------------- |\n| 类型安全 | 将运行时错误提前到编译期  |\n| 表达能力 | 明确数据结构中的类型意图  |\n| 复用能力 | 让同一套代码服务于多种类型 |\n\n---\n\n## 二、Java 泛型的核心模型\n\nJava 泛型可以抽象为两个基本要素：\n\n```\n泛型 = 类型参数化 + 类型约束\n```\n\n* **类型参数化**：让类或方法不再依赖具体类型\n* **类型约束**：对参数化类型施加边界限制\n\n---\n\n### 泛型知识结构总览\n\n```\n泛型\n│\n├── 类型参数化\n│   ├── 泛型类\n│   ├── 泛型接口\n│   └── 泛型方法\n│\n├── 类型约束\n│   ├── 上界约束 extends\n│   ├── 下界约束 super\n│   └── 通配符 ?\n│\n├── 使用原则\n│   └── PESC 原则\n│\n└── 实现机制\n    └── 泛型擦除\n```\n\n---\n\n## 三、类型参数化的三种形态\n\n### 1. 泛型类\n\n泛型类的本质：\n\n> 把“类的类型信息”参数化\n\n```java\nclass Box<T> {\n    private T value;\n\n    public Box(T value) {\n        this.value = value;\n    }\n\n    public T get() {\n        return value;\n    }\n}\n```\n\n在这个结构中：\n\n* `T` 不是某个具体类型\n* 而是一个类型占位符\n\n---\n\n### 2. 泛型方法\n\n泛型方法的本质：\n\n> 把“方法的类型信息”参数化\n\n```java\npublic static <T> T identity(T obj) {\n    return obj;\n}\n```\n\n这里：\n\n* `<T>` 是方法的类型参数声明\n* 后面的 `T` 是返回值类型\n\n---\n\n### 3. 泛型接口\n\n与泛型类类似，接口也可以参数化：\n\n```java\ninterface Converter<F, T> {\n    T convert(F from);\n}\n```\n\n---\n\n### 小结\n\n这三种形态本质一致：\n\n| 形态   | 抽象层级     |\n| ---- | -------- |\n| 泛型类  | 对数据结构参数化 |\n| 泛型接口 | 对行为参数化   |\n| 泛型方法 | 对单个逻辑参数化 |\n\n---\n\n## 四、类型约束：对泛型的边界控制\n\n单纯的类型参数化过于自由，因此需要约束。\n\n---\n\n### 1. 上界约束（extends）\n\n```java\n<T extends Comparable>\n```\n\n含义：\n\n> T 必须是 Comparable 的子类\n\n---\n\n可以指定多个接口：\n\n```java\n<T extends Comparable & Serializable>\n```\n\n---\n\n### 2. 通配符\n\n通配符本质是：\n\n> 对“泛型类型参数”的一种灵活表达\n\n---\n\n#### 上界通配符\n\n```java\n<? extends T>\n```\n\n语义：\n\n> 接受 T 或 T 的子类型\n\n---\n\n#### 下界通配符\n\n```java\n<? super T>\n```\n\n语义：\n\n> 接受 T 或 T 的父类型\n\n---\n\n#### 无界通配符\n\n```java\n<?>\n```\n\n语义：\n\n> 不关心具体类型\n\n---\n\n## 五、PESC 原则：泛型使用的工程哲学\n\n### 1. 原则本身\n\n**Producer Extends Consumer Super**\n\n* 生产者（读）用 extends\n* 消费者（写）用 super\n\n---\n\n### 2. 原理本质\n\n这个原则并不是一个“经验口诀”，而是类型系统约束的必然结果。\n\n---\n\n#### 上界通配符：协变视角（适合读）\n\n```java\nList<? extends Fruit> basket;\n```\n\n特点：\n\n* 可以安全读取为 Fruit\n* 不能安全写入\n\n本质原因：\n\n> 编译器无法确定具体子类型\n\n---\n\n#### 下界通配符：逆变视角（适合写）\n\n```java\nList<? super Apple> basket;\n```\n\n特点：\n\n* 可以安全写入 Apple\n* 读取时只能当作 Object\n\n本质原因：\n\n> 只能保证是 Apple 的父类，但不知道具体是哪一层\n\n---\n\n### 3. 工程意义\n\nPESC 的真正含义是：\n\n| 场景     | 选择            |\n| ------ | ------------- |\n| 主要用于读取 | `? extends T` |\n| 主要用于写入 | `? super T`   |\n\n---\n\n### 4. API 设计中的体现\n\nJava API 中的经典例子：\n\n```java\npublic static <T> void copy(\n    List<? super T> dest,\n    List<? extends T> src\n)\n```\n\n设计意图极为清晰：\n\n* src：生产者 → extends\n* dest：消费者 → super\n\n---\n\n## 六、泛型的实现机制：类型擦除\n\n### 1. 核心事实\n\n> JVM 并不真正理解泛型\n\n在虚拟机层面：\n\n* 只有普通类和方法\n* 不存在真实的泛型类型\n\n---\n\n### 2. 泛型擦除的过程\n\n编译阶段：\n\n* 泛型参数被擦除为限定类型\n* 必要时插入类型转换\n* 自动生成桥方法\n\n---\n\n### 3. 为什么要擦除？\n\n本质原因：\n\n> 历史兼容性\n\n* JVM 早于泛型诞生\n* 为了兼容旧字节码\n* 避免虚拟机层面的重大改造\n\n---\n\n### 4. 带来的代价\n\n由于擦除：\n\n* 运行时无法获取 T 的真实类型\n* 反射操作受限\n* 某些场景需要额外手段（TypeToken）\n\n---\n\n## 七、类型系统视角\n\n泛型问题本质是一个类型系统问题。\n\n---\n\n### 1. 类型变化关系\n\n设：\n\n* A ≤ B 表示 A 是 B 的子类型\n* f(·) 表示类型构造器\n\n---\n\n#### 协变（covariant）\n\n```\nA ≤ B  ⇒  f(A) ≤ f(B)\n```\n\n---\n\n#### 逆变（contravariant）\n\n```\nA ≤ B  ⇒  f(B) ≤ f(A)\n```\n\n---\n\n#### 不变（invariant）\n\n```\nf(A) 与 f(B) 无关\n```\n\n---\n\n### 2. Java 中的选择\n\n| 形态          | 类型关系 |\n| ----------- | ---- |\n| List<T>     | 不变   |\n| ? extends T | 协变   |\n| ? super T   | 逆变   |\n\n---\n\n### 3. 本质联系\n\n* Java 默认选择“不变”\n* 用通配符实现协变和逆变\n* PESC 原则正是这一类型关系的工程化表达\n\n---\n\n## 八、对泛型的整体认知\n\n我们可以把 Java 泛型总结为：\n\n> 一套在“静态类型系统约束”与“历史兼容性”之间权衡的设计\n\n---\n\n### 三层模型\n\n| 层次  | 含义                      |\n| --- | ----------------------- |\n| 语法层 | `<T>`、`extends`、`super` |\n| 语义层 | 类型参数化与类型约束              |\n| 实现层 | 类型擦除与桥方法                |\n\n---\n\n## 九、总结\n\n### 1. 泛型的本质\n\n* 不是语法糖\n* 而是类型系统的扩展\n\n---\n\n### 2. 泛型的核心价值\n\n* 类型安全\n* 更好的抽象\n* 更强的复用\n\n---\n\n### 3. 使用哲学\n\n* 读：协变\n* 写：逆变\n* 读写混合：谨慎设计\n\n## 关联内容（自动生成）\n\n- [/编程语言/JAVA/高级/反射.md](/编程语言/JAVA/高级/反射.md) Java反射与泛型结合使用时，可以实现更强大的动态类型处理能力\n- [/编程语言/JAVA/高级/注解.md](/编程语言/JAVA/高级/注解.md) 泛型与注解结合使用，可以在编译时进行更精确的类型检查和元数据处理\n- [/编程语言/JAVA/高级/集合/集合.md](/编程语言/JAVA/高级/集合/集合.md) Java集合框架大量使用泛型，提供了类型安全的数据结构操作\n- [/编程语言/JAVA/高级/Lambda表达式.md](/编程语言/JAVA/高级/Lambda表达式.md) Lambda表达式与泛型结合，增强了函数式编程的类型安全性和表达能力\n- [/编程语言/编程范式/面向对象.md](/编程语言/编程范式/面向对象.md) 泛型是面向对象编程的重要特性，体现了参数化类型的抽象思想\n- [/编程语言/C++.md](/编程语言/C++.md) C++模板与Java泛型在设计理念上有相似之处，但实现机制有所不同\n- [/编程语言/编程范式/函数式编程.md](/编程语言/编程范式/函数式编程.md) 函数式编程中的高阶类型与泛型有密切关系，都涉及类型参数化\n- [/软件工程/设计模式/创建型模式.md](/软件工程/设计模式/创建型模式.md) 创建型设计模式中经常使用泛型来提供类型安全的对象创建机制\n","metadata":"tags: ['编程语言']","hasMoreCommit":false,"totalCommits":10,"commitList":[{"date":"2026-02-12T14:07:03+08:00","author":"MY","message":"doc: 整理标签","hash":"290b3e8ad18f48832ac282290238d020fc030a88"},{"date":"2026-01-15T16:14:34+08:00","author":"MY","message":"docs(java): 完善Java泛型文档内容","hash":"319b5561d8c658fdfef249c1478a73992499c626"},{"date":"2025-09-18T11:51:44+08:00","author":"MY","message":"docs(JAVA): 更新类型变化关系说明文档","hash":"d34034b1eb88fb7a81c2d2aa87b994388c7fb12e"},{"date":"2024-11-18T16:40:55+08:00","author":"MY","message":"📦Java 高级","hash":"2b21c6566aa4db8dff3d81003dea531cbe044061"},{"date":"2021-08-13T15:53:02+08:00","author":"cjiping","message":"✏更新 Java 泛型","hash":"3216f07659fcd9b30affce1a7bedfa4f0f359013"},{"date":"2020-09-16T15:21:23+08:00","author":"MY","message":"✏更新 Java 泛型","hash":"3643aace3c2b03a431f09574d1a9c1aa3ac04b5e"},{"date":"2020-08-04T09:10:50+08:00","author":"MY","message":"✏更新 JAVA 泛型","hash":"ded7b410e40601858403063b3af652fe59e3976a"},{"date":"2019-10-30T14:08:43+08:00","author":"MY","message":"更新完JAVA泛型","hash":"7aead163eded19c1e3a30f3242a87c1740a762ab"},{"date":"2019-10-29T22:49:09+08:00","author":"MY","message":"新增泛型-本质","hash":"357018d3c8f831fb48c2402eb18acf1945cb1b2b"},{"date":"2019-10-28T23:06:11+08:00","author":"MY","message":"新增JAVA泛型","hash":"ca393f9048c77476550888b49330418f8eb4ccca"}],"createTime":"2019-10-28T23:06:11+08:00"}