掌握Java泛型关键在于理解编译期约束与类型擦除,再结合通配符(PECS原则)、泛型方法、避坑实践四方向深入应用。

掌握 Java 泛型高级编程技巧,关键不是死记语法,而是理解“编译期约束”和“类型擦除”这两个底层逻辑,再结合典型场景反复实践。下面从四个实用方向切入,帮你避开常见误区,真正用得稳、用得巧。
吃透类型擦除:明白泛型只在编译期起作用
Java 泛型没有运行时类型信息——所有 <string></string>、<user></user> 在字节码里都会变成 Object。这意味着:
- 不能用
if (list instanceof List<string>)</string>判断泛型类型(编译不通过) - 不能在泛型类中直接 new
T()(类型信息已擦除,可用Supplier<t></t>或反射绕过) - 静态方法/字段不能引用类的类型参数(如
static T DEFAULT是非法的)
用好通配符:读写分离是核心原则
通配符不是为了炫技,而是解决“子类型兼容”问题。记住一句话:Producer Extends,Consumer Super(PECS)。
-
List extends Number>:只能读,不能 add(除了null),因为实际可能是List<integer></integer>或List<double></double>,你无法保证加进去的元素安全 -
List super Integer>:只能写,不能安全地 get 出具体类型(比如取出来可能是Object),但可以放心 addInteger及其子类 - 不要滥用
List>——它等价于List<object></object>,失去类型约束,仅适合纯遍历或工具方法内部临时使用
写泛型方法比泛型类更灵活
很多场景其实不需要整个类泛化,一个泛型方法就够了,还能自动类型推断,代码更干净:
立即学习“Java免费学习笔记(深入)”;
- 交换数组元素:
public static <t> void swap(T[] a, int i, int j)</t> - 构建通用 map:
public static <k> Map<k> of(K k, V v) { ... }</k></k> - 避免“类型污染”:方法级泛型不会让调用方被迫泛化整个上下文,耦合更低
工程中必须避开的坑
这些错误在真实项目里高频出现,轻则编译警告,重则运行时 ClassCastException:
- 别用原始类型(
List)代替泛型(List<string></string>),尤其在方法参数和返回值中 - 泛型数组不能直接创建:
new ArrayList<string>[10]</string>编译失败,改用new ArrayList[10]+ @SuppressWarnings("unchecked")(需谨慎) - 泛型与反射混用时,用
ParameterizedType获取泛型实参(如 Spring 的RestTemplate.exchange就靠它还原ResponseEntity<user></user>) - 自定义泛型工具类时,优先提供
asList(T...)这类工厂方法,而不是暴露裸泛型构造器



















