题目
Java泛型基础 - 理解类型擦除和类型安全
信息
- 类型:问答
- 难度:⭐
考点
泛型概念,类型擦除,类型安全
快速回答
Java泛型的主要作用是提供编译时类型检查,防止运行时类型转换错误。核心要点:
- 泛型通过类型参数化增强代码复用和类型安全
- Java泛型采用类型擦除实现,编译后替换为Object或边界类型
- 泛型可防止
ClassCastException,如List<String>只能添加字符串
一、泛型核心原理
Java泛型本质是参数化类型,在编译阶段进行类型检查,运行时通过类型擦除(Type Erasure)实现:
// 编译前
List<String> stringList = new ArrayList<>();
stringList.add("Hello");
// 编译后(类型擦除效果)
List stringList = new ArrayList(); // 类型参数被擦除
stringList.add("Hello"); // 实际存储为Object类型擦除规则:
- 无边界泛型(如
<T>)擦除为Object - 有边界泛型(如
<T extends Number>)擦除为边界类型(Number)
二、类型安全示例
泛型如何避免类型错误:
// 非泛型代码 - 可能引发ClassCastException
List rawList = new ArrayList();
rawList.add(123); // 添加Integer
String s = (String) rawList.get(0); // 运行时错误!
// 泛型代码 - 编译时即报错
List<String> safeList = new ArrayList<>();
safeList.add(123); // 编译错误:类型不匹配
safeList.add("Text"); // 仅允许String类型三、最佳实践与常见错误
最佳实践:
- 优先使用泛型集合(如
List<T>而非原生List) - 方法中使用泛型参数:
<T> void process(T item) {...} - 通配符边界:
List<? extends Number>接受Number子类
常见错误:
- 错误1:尝试创建泛型数组
// 错误写法!
T[] arr = new T[10];
// 正确替代方案:
List<T> list = new ArrayList<>(); - 错误2:忽略编译器警告(如未经检查的类型转换)
- 错误3:运行时获取泛型类型(因类型擦除,
list.getClass()无法获得String)
四、扩展知识
- 通配符使用:
List<?>(未知类型),List<? super Integer>(下限) - 类型擦除的例外:通过反射可获取方法签名中的泛型信息(如
Method.getGenericParameterTypes()) - 与C#泛型区别:Java泛型无运行时类型信息,C#保留类型参数