面试题答案
一键面试类型擦除机制
Java泛型的类型擦除指的是,在编译阶段,所有的泛型类型信息都会被擦除掉。编译器在编译带有泛型的代码时,会将泛型类型替换为它们的限定类型(通常是Object
,如果有上限则替换为上限类型)。例如,对于List<String>
,在编译后实际的类型会被擦除为List
,其中String
类型信息被去除。
对代码产生的影响
- 无法在运行时获取泛型类型信息:由于类型信息在编译后被擦除,运行时无法确切知道泛型的实际类型。例如:
List<String> list = new ArrayList<>();
list.add("Hello");
// 以下代码无法获取到泛型参数String的实际类型
Type type = list.getClass().getGenericSuperclass();
- 可能导致编译警告:当使用了未经检查的泛型操作时,编译器会发出警告。比如将一个
List
赋值给List<String>
:
List list = new ArrayList();
list.add(123);
List<String> stringList = list; // 这里会产生未经检查的转换警告
String str = stringList.get(0); // 运行时会抛出ClassCastException
- 泛型方法和泛型类的桥接方法:在涉及到泛型的继承和多态时,编译器会生成桥接方法来保持多态的正确性。例如:
class GenericBase<T> {
public T get(T t) { return t; }
}
class GenericSub extends GenericBase<String> {
@Override
public String get(String t) { return t; }
}
在编译后,为了保证多态,编译器会为GenericSub
生成一个桥接方法:
public Object get(Object t) {
return get((String) t);
}
- 无法创建泛型数组:由于类型擦除,不能直接创建泛型数组。例如:
// 以下代码会编译错误
T[] array = new T[10];
因为编译后T
被擦除,实际类型不确定,所以不能创建这样的数组。