掌握Java泛型关键在于理解类型确定时机、擦除机制、桥方法、通配符意图及有界类型约束;数组不能new T[],静态成员不可用类类型参数,基本类型不可实例化泛型。

掌握 Java 泛型高级特性,关键不在死记语法,而在理解“类型何时确定”“擦除后如何工作”“边界怎么约束行为”。下面从四个最常卡壳又最实用的维度讲清楚。
搞懂类型擦除和桥方法
泛型只在编译期起作用,运行时所有 <t></t> 都被擦成 Object(或上界类型),这是很多困惑的根源。比如:
-
List<string></string>和List<integer></integer>运行时都是List,不能用instanceof判断泛型类型 - 子类重写泛型父类方法时,编译器会自动生成“桥方法”来保持多态调用正确——这不是你写的,但必须知道它存在,否则会看不懂反编译代码或调试时的方法跳转
- 数组不能直接创建泛型类型:
new T[10]编译报错,因为擦除后 T 是 Object,但 JVM 要求数组在创建时明确元素类型;常用写法是(T[]) new Object[10],并配合@SuppressWarnings("unchecked")
用对通配符:?、? extends、? super
通配符不是偷懒省略,而是明确表达“读”或“写”的意图:
-
List>:只适合做参数传递,不能add()(除了null),但可以安全get()成Object -
List extends Number>:能读出Number或其子类(如Integer、Double),但不能add()任何具体类型(连Number都不行),因为实际可能是List<integer></integer>,加个Double就破坏类型安全 -
List super Integer>:能往里add(Integer),也能读出Object,但不能假设读出来的是Integer——因为实际可能是List<number></number>或List<object></object>
写好泛型方法与有界类型参数
泛型方法比泛型类更灵活,尤其适合工具类。重点看类型参数的约束:
立即学习“Java免费学习笔记(深入)”;
- 方法前声明:
public static <t extends comparable>> T max(T a, T b)</t>—— 表示 T 必须可比较,才能调用compareTo() - 多个上界用
&连接:<t extends runnable closeable></t>,表示 T 必须同时实现两个接口 - 避免无意义的
<t></t>:如果方法体里没用到 T 的任何特有方法(只当 Object 用),那其实不需要泛型,用普通参数即可
避开常见陷阱
这些错误高频出现,往往编译通过但逻辑脆弱:
- 泛型类不能继承
Exception或Throwable子类(擦除后异常类型信息丢失,JVM 无法校验 throws) - 静态方法/字段不能直接引用类的类型参数(如
static T value不合法),因为静态成员属于类本身,而泛型类型参数属于实例 - 不能用基本类型实例化泛型:
List<int></int>错误,必须用包装类List<integer></integer> - 泛型类型不能用于
switch、instanceof、new构造(如new T()),因擦除后无类型信息


















