Java反射调用私有泛型send方法出现NoSuchMethodException的问题咨询
解决反射调用私有泛型方法找不到的问题
这个问题的核心是Java泛型擦除在搞鬼,加上你对反射获取方法的参数类型匹配有误,导致JVM找不到目标方法。我给你一步步拆解解决思路:
1. 先搞懂泛型擦除对方法签名的影响
Java的泛型是编译时特性,运行时所有泛型类型都会被擦除。你的私有泛型方法:
private <T> boolean send(String topic, Message protonMsg, Map<String, Object> properties, SendOptions sendOptions, CompletionListener<T> listener, T context) throws StoppedException
编译后会变成这样的“原始”方法签名(泛型被擦除):
private boolean send(String topic, Message protonMsg, Map properties, SendOptions sendOptions, CompletionListener listener, Object context) throws StoppedException
划重点:
CompletionListener<T>擦除为CompletionListener(和你写的CompletionListener.class匹配)T context擦除为Object(因为T没有指定上界,默认上界是Object),而你用了Void.class,这就是找不到方法的关键原因!
2. 修正反射获取方法的代码
把最后一个参数类型从Void.class改成Object.class,才能匹配擦除后的方法签名:
Method sendMethod = NonBlockingClientImpl.class.getDeclaredMethod( "send", String.class, Message.class, Map.class, SendOptions.class, CompletionListener.class, Object.class // 替换原来的Void.class );
3. 允许访问私有方法
因为目标方法是private的,必须调用setAccessible(true)来绕过访问权限检查:
sendMethod.setAccessible(true);
4. 调用方法(示例)
假设你要传入Void类型的context,直接传null即可(因为Void类不能实例化):
// 实例化目标类对象 NonBlockingClientImpl clientInstance = new NonBlockingClientImpl(); // 调用方法,注意强转返回值为boolean boolean result = (boolean) sendMethod.invoke( clientInstance, "your-topic", protonMsg, properties, sendOptions, yourCompletionListener, // 你的CompletionListener实现类实例 null // 对应T context,Void类型传null );
额外提醒
如果你的泛型T有上界(比如<T extends Number>),那擦除后的类型就是Number.class,这时候要把最后一个参数类型改成Number.class。另外,如果类中有重载的send方法,一定要确保参数列表完全匹配,避免获取到错误的重载方法。
内容的提问来源于stack exchange,提问作者Weizen
相关产品推荐
相关产品推荐

