Java泛型类型擦除导致反射invoke只能按原始类型匹配参数,无法基于泛型精确匹配;需用getGenericParameterTypes()获取真实泛型信息,注意桥接方法干扰。
Java 泛型的类型擦除会直接影响反射调用
时的参数匹配逻辑——不是因为泛型本身“干扰”了方法查找,而是因为擦除后的方法签名在字节码中已不包含泛型信息,导致反射无法基于泛型参数做精确匹配,只能按原始类型(raw type)匹配。
方法签名在运行时只剩原始类型
泛型方法或泛型类中的方法,在编译后其参数和返回值类型均被擦除为边界类型(无界则为
)。例如:
→ 擦除为
→ 擦除为
反射调用
时,
对象是通过
或
获取的,而这些方法**只认擦除后的签名**。你传入
,反射底层看到的只是
;传入
,它只当它是
或其上界类型。
参数类型检查完全失效
编译期的泛型约束在运行时不生效,所以反射可以绕过所有类型限制:
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
立即学习
“
Java免费学习笔记(深入)
”;
一个声明为
的泛型方法(如在
中),擦除后实际是
用反射调用时,传入
(
)也能成功,不会抛
这和直接调用不同:编译器会对
报错,但反射跳过了编译检查
获取泛型参数信息需额外手段
若你想在反射中还原真实泛型参数(比如做类型校验或自动转换),不能依赖
(它返回的是擦除后的
),而要改用:
返回
,其中可能是
对
调用
才能拿到
、
等实参
注意:该信息仅保留在方法声明处(如字段、方法签名、父类继承关系中),运行时对象实例本身不携带泛型参数
桥接方法可能干扰 method 查找
泛型类重写父类方法时,编译器会生成桥接方法(bridge method),它和原始方法共存于字节码中。例如:
重写了
会生成一个桥接方法
,再委托给擦除后的
用
可能拿到桥接方法而非你预期的泛型方法,影响参数处理逻辑
建议用
配合
过滤,或优先用
判断语义意图
invokeObjectpublic void process(List data) public void process(List data)public T parse(String s) public Number parse(String s)Method.invoke(obj, args...)MethodClass.getMethod()getDeclaredMethod()ArrayListArrayListIntegerObjectvoid add(Integer x)Boxvoid add(Object x)"hello"StringIllegalArgumentExceptionbox.add("hello")method.getParameterTypes()Class[]method.getGenericParameterTypes()Type[]ParameterizedTypeParameterizedTypegetActualTypeArguments()String.classInteger.classclass Child extends Parentset(T t)set(Object o)set(String s)getDeclaredMethod("set", Object.class)getMethods()isBridge()getGenericParameterTypes()