泛型是Java中在编译期实现类型安全的参数化类型机制,通过类型占位符(如T)和编译时校验,提前拦截类型错误,避免运行时ClassCastException,并提升代码可读性与复用性。

泛型是Java中把“类型”当作参数来用的一种机制,不是运行时才确定类型,而是在写代码时就声明、在编译时就校验。它的核心作用,就是把本该在运行时才能发现的类型错误,提前到编译阶段拦截住。
泛型本质是参数化类型
你可以把它理解成“模板”:定义类、方法或接口时不写死具体类型(比如String或Integer),而是用一个占位符(如
- List<String> 表示这个列表只接受字符串,编译器会阻止你往里加数字或对象;
- Box<Integer> 表示这个盒子只能装整数,调用getItem()直接返回Integer,不用强转;
- 如果误写 list.add(123) 到 List<String> 中,编译器立刻报错,不生成字节码。
它怎么实现编译期类型安全
泛型的安全性不是靠虚拟机或运行时检查,而是编译器在编译过程中做静态分析:
- 对所有泛型结构(如ArrayList<T>)进行类型推导,验证插入、读取、赋值是否符合声明的类型约束;
- 擦除(Type Erasure)后保留的桥接方法和类型检查逻辑,仍足以捕获不合法操作;
- 一旦类型不匹配,比如把Double塞进List<Boolean>,根本通不过编译,不会等到运行时报ClassCastException。
对比没有泛型的老写法
JDK 1.5之前,集合全用Object,导致两个典型问题:
立即学习“Java免费学习笔记(深入)”;
- 存的时候没限制——list.add("hello") 和 list.add(new Date()) 都能通过;
- 取的时候要强转——String s = (String) list.get(0),一旦里面其实是Date,运行就崩;
- 泛型把这两步都解决了:存的时候卡住非法类型,取的时候自动推导类型,无需括号强转。
泛型提升的不只是安全性,还有可读性与复用性
看到 Map<String, List<Order>>,你就清楚这是“订单列表按用户ID索引”的结构;写一个泛型方法 public <T> T getFirst(List<T> list),就能同时用于String、User、BigDecimal等任意类型,逻辑只写一遍。


















