← [ BACK_TO_NOTES ]

泛型擦除与可具体化边界

泛型类型擦除如何工作:运行时可见什么、为何不能 new T[],以及桥接方法直觉。

#concept #growing #dev #java

[!info] related notes

泛型擦除与可具体化边界

这个概念为什么出现

学了泛型仍会对 List<String> 运行时类型、异常捕获、数组创建感到困惑。根因是 Java 泛型主要是编译期机制,采用类型擦除兼容历史虚拟机。

[!abstract] 一句话理解 类型变量擦除为最左边的上界(无显式上界时为 Object);同一泛型类的不同参数化共享运行时类,因此不能依赖 T 做可具体化操作,数组与异常等有专门限制。

最小可运行示例

场景:运行时看两个参数化列表的类

import java.util.*;

public class ErasurePeek {
    public static void main(String[] args) {
        List<String> a = new ArrayList<>();
        List<Integer> b = new ArrayList<>();
        System.out.println(a.getClass() == b.getClass()); // true
        Object unknown = a;
        // unknown instanceof List<String> // 编译错误:无法安全检查元素类型
        System.out.println(unknown instanceof List<?>);
    }
}
javac ErasurePeek.java && java ErasurePeek

期望:

true
true

结合场景再看三个关注点

  1. 运行时类相同不代表编译期类型相同。
  2. 强制转换由编译器插入,不安全用法会在运行期炸。
  3. 类型令牌表达的是类型描述,不会自动验证集合内每个元素。

核心概念与准确模型

1. 擦除规则直觉

  • 无界 → Object
  • T extends Number → Number;交叉上界如 T extends Number & Comparable<T> 也擦除为最左边的 Number。
  • 桥接方法保持多态

2. 不可做的事

  • new T() / new T[]
  • 泛型类不能继承 Throwable;catch (T e) 不能捕获类型变量,但 throws T(T extends Throwable)可以合法。
  • Object 不能用 instanceof List<String> 检查。Java 16+ 允许不需要 unchecked 转换的参数化检查,例如静态类型为 List<String> 的 a instanceof ArrayList<String>;这只检查实现类,不检查元素。

3. reification

可具体化(reifiable)类型包括基本类型、非泛型类、raw type、仅使用无界通配符的参数化类型(如 List<?>),以及元素类型可具体化的数组。new List<?>[n] 合法,new List<String>[n] 和 new T[n] 不合法;后两种数组类型仍可出现在声明中。

边界情况与反直觉行为

  1. 反射 getGeneric* 可看到签名信息(类文件属性),不等于完整运行时 reify。
  2. 原始类型触发未检查警告。
  3. 非可具体化类型的泛型变参可能导致 heap pollution;不是每次调用都会污染。

常见误区

[!warning] 常见误区:认为擦除=泛型没用 编译期安全与 API 表达仍然极有价值。

工程实践

  1. 避免 raw type。
  2. Class<T> 可传递运行时类,但没有 List<String>.class;超类型令牌(如库提供的 TypeToken)可捕获声明中的嵌套类型参数,不能据此保证任意对象的内容符合声明。
  3. 抑制警告仅限边界。
  4. 读 javap 看桥接方法建立直觉。

本节总结

  • 擦除解释运行时限制
  • 编译期仍强约束
  • 与数组 reify 对比记忆

自测题

  1. 为什么不能创建泛型数组 new T[n]?
  2. 桥接方法为了什么?
参考答案
  1. 擦除与数组可具体化冲突,类型安全难保证。
  2. 在擦除后仍保持覆盖与调用的二进制兼容/多态分派。

延伸阅读与资料来源

资料类型支撑内容
Type Erasure Tutorial教程擦除
JLS 4.6 Type Erasure规范规则
JLS 15.20.2 instanceof规范Java 16 起的参数化类型检查边界
创建于 2026/7/15 更新于 2026/10/6
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本