桥接方法中参数的泛型类型信息丢失问题求助
问题分析与解答
代码示例
class A { public void doit(List<String> args) { } public static class C extends A { } public static void main(String[] args) throws Exception { Method m = C.class.getMethod("doit", List.class); Type ptype = m.getParameters()[0].getParameterizedType(); System.out.println("type is -> " + ptype); } }
输出结果
type is -> interface java.util.List
问题
通过反射获取到的doit()方法是编译器生成的合成桥接方法,但参数的泛型类型信息String丢失了。请问这是什么原因?将类A设为public是否是获取泛型类型信息的可行办法?
原因分析
- 桥接方法的类型擦除特性:Java泛型在编译阶段会执行类型擦除操作,
List<String>会被擦除为原始类型List。子类C继承A后,编译器会自动生成桥接方法以保证多态语义,这个桥接方法的参数是擦除后的List,本身不携带泛型参数String的信息,所以反射获取时自然拿不到。 - 泛型信息的存储逻辑:泛型的具体参数信息仅保留在定义该方法的父类
A的原始方法中,编译器合成的桥接方法不会保留这些细节。
类A设为public的可行性
将类A设为public无法解决问题。因为问题的根源是泛型类型擦除和桥接方法的合成机制,和类的访问修饰符没有关联。无论A的访问级别如何,桥接方法都会被生成,且参数依然是擦除后的原始类型。
正确获取泛型信息的方式
要获取完整的泛型参数类型,应该直接从父类A的原始方法中读取:
Method m = A.class.getMethod("doit", List.class); Type ptype = m.getGenericParameterTypes()[0]; System.out.println("type is -> " + ptype); // 输出:type is -> java.util.List<java.lang.String>
内容的提问来源于stack exchange,提问作者Jacky Wang
相关产品推荐
相关产品推荐

