面试题答案
一键面试类型擦除带来的问题
- 运行时类型信息丢失:在Java中,泛型是在编译期实现的,运行时类型参数会被擦除。例如对于
List<List<Map<String, T>>>
,运行时T
的具体类型信息会丢失,这可能导致在需要确切类型信息进行操作时出现问题,比如无法直接在运行时检查Map
中值的类型。 - 无法创建泛型数组:由于类型擦除,不能直接创建泛型数组,如
List<List<Map<String, T>>>[] array = new List<List<Map<String, T>>>[];
是不允许的,这在需要使用泛型数组来存储这种多层嵌套结构时会带来不便。 - 潜在的类型安全问题:如果在代码中进行一些绕过泛型检查的操作(例如通过反射),可能会在运行时出现
ClassCastException
,因为编译期的泛型检查在运行时已不存在。
解决方法
- 使用类型令牌(Type Token):通过传递一个表示具体类型的
Class
对象来保留类型信息。例如:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class GenericUtil {
public static <T> List<List<Map<String, T>>> createNestedStructure(Class<T> type) {
List<List<Map<String, T>>> result = new ArrayList<>();
// 这里只是示例,实际可以根据需求填充数据
List<Map<String, T>> innerList = new ArrayList<>();
Map<String, T> map = new HashMap<>();
try {
T instance = type.newInstance();
map.put("key", instance);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
innerList.add(map);
result.add(innerList);
return result;
}
}
public class Main {
public static void main(String[] args) {
List<List<Map<String, Integer>>> structure = GenericUtil.createNestedStructure(Integer.class);
System.out.println(structure);
}
}
- 引入通配符:在使用多层嵌套泛型结构时,合理使用通配符可以增强API的灵活性。例如:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class WildcardExample {
public static void printNestedMap(List<List<Map<String, ?>>> nestedList) {
for (List<Map<String, ?>> innerList : nestedList) {
for (Map<String, ?> map : innerList) {
System.out.println(map);
}
}
}
public static void main(String[] args) {
List<List<Map<String, Integer>>> list = new ArrayList<>();
List<Map<String, Integer>> innerList = new ArrayList<>();
Map<String, Integer> map = new HashMap<>();
map.put("num", 10);
innerList.add(map);
list.add(innerList);
printNestedMap(list);
}
}
- 使用反射获取类型信息:在某些情况下,可以通过反射来获取泛型类型信息。例如:
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class ReflectiveGenericUtil {
public static <T> List<List<Map<String, T>>> getNestedStructure(Object instance) {
Type genericSuperclass = instance.getClass().getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (actualTypeArguments.length > 0) {
Type type = actualTypeArguments[0];
if (type instanceof Class) {
Class<T> clazz = (Class<T>) type;
List<List<Map<String, T>>> result = new ArrayList<>();
// 填充数据示例
List<Map<String, T>> innerList = new ArrayList<>();
Map<String, T> map = new HashMap<>();
try {
T instanceObj = clazz.newInstance();
map.put("key", instanceObj);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
innerList.add(map);
result.add(innerList);
return result;
}
}
}
return null;
}
}
class MyGenericClass<T> {
// 这里可以有其他逻辑
}
public class ReflectiveMain {
public static void main(String[] args) {
MyGenericClass<Integer> myClass = new MyGenericClass<>();
List<List<Map<String, Integer>>> structure = ReflectiveGenericUtil.getNestedStructure(myClass);
System.out.println(structure);
}
}
通过这些方法,可以在一定程度上解决类型擦除带来的问题,确保API的正确性和兼容性。