面试题答案
一键面试难题
- 获取
Outer
的泛型类型参数:虽然outer
是Outer<List<String>>
的实例,但通过普通反射获取泛型信息时,在运行时泛型类型信息会被擦除,无法直接获取到<List<String>>
这种精确的泛型类型,只能获取到原始类型Outer
。 - 获取
Inner
的泛型类型参数:对于inner
,同样存在泛型类型擦除问题。并且Inner
是嵌套类,获取其泛型类型不仅要克服类型擦除,还要处理嵌套结构带来的复杂性,常规反射难以直接获取到<Integer>
这个泛型参数。
解决方案
- 使用
ParameterizedType
接口:- 要获取
Outer
的泛型类型,可以通过获取声明outer
变量的字段或方法的泛型类型来间接获取。假设outer
是在某个类的字段中声明,可以通过如下代码:
- 要获取
Field field = OuterContainer.class.getDeclaredField("outer");
Type genericType = field.getGenericType();
if (genericType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (actualTypeArguments.length > 0) {
Type outerActualType = actualTypeArguments[0];
// 这里outerActualType就是List<String>的Type,还可以进一步处理
}
}
- 对于`Inner`,由于`Inner`是`Outer`的内部类,先获取`Outer`的类型,再获取`Inner`的构造函数的泛型类型。假设通过反射创建`Inner`实例:
Constructor<Outer.Inner> constructor = Outer.class.getDeclaredInnerClass("Inner").getConstructor();
Type genericReturnType = constructor.getGenericReturnType();
if (genericReturnType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericReturnType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (actualTypeArguments.length > 0) {
Type innerActualType = actualTypeArguments[0];
// 这里innerActualType就是Integer的Type
}
}
- 利用
TypeToken
类(Guava库):Guava库中的TypeToken
类能更方便地处理泛型类型。例如:
TypeToken<Outer<List<String>>> outerToken = new TypeToken<Outer<List<String>>>() {};
Type outerType = outerToken.getType();
// 处理outerType获取具体泛型信息
TypeToken<Outer.Inner<Integer>> innerToken = new TypeToken<Outer.Inner<Integer>>() {};
Type innerType = innerToken.getType();
// 处理innerType获取具体泛型信息
通过这种方式,可以在编译时保留泛型信息,从而在运行时准确获取泛型类型。