我正在编写一个使用反射来动态查找和调用方法的库。只给出一个对象,一个方法名和一个参数列表,我需要调用给定的方法,好像方法调用是在代码中明确写出的一样。
I'm writing a library that uses reflection to find and call methods dynamically. Given just an object, a method name, and a parameter list, I need to call the given method as though the method call were explicitly written in the code.
我'我一直在使用以下方法,它适用于大多数情况:
I've been using the following approach, which works in most cases:
static void callMethod(Object receiver, String methodName, Object[] params) { Class<?>[] paramTypes = new Class<?>[params.length]; for (int i = 0; i < param.length; i++) { paramTypes[i] = params[i].getClass(); } receiver.getClass().getMethod(methodName, paramTypes).invoke(receiver, params); }但是,其中一个参数是子类该方法支持的类型之一,反射API抛出 NoSuchMethodException 。例如,如果接收者的类定义了 testMethod(Foo),则以下操作失败:
However, when one of the parameters is a subclass of one of the supported types for the method, the reflection API throws a NoSuchMethodException. For example, if the receiver's class has testMethod(Foo) defined, the following fails:
receiver.getClass().getMethod("testMethod", FooSubclass.class).invoke(receiver, new FooSubclass());即使有效:
receiver.testMethod(new FooSubclass());如何解决此问题?如果方法调用是硬编码的,则没有问题 - 编译器只使用重载算法来选择最适用的方法。但它不适用于反射,这就是我需要的。
How do I resolve this? If the method call is hard-coded there's no issue - the compiler just uses the overloading algorithm to pick the best applicable method to use. It doesn't work with reflection, though, which is what I need.
提前致谢!
推荐答案这比你开始的时间要长一点,但是这样做你要求的......还有一点 - 例如,callMethod(接收器,voidMethod),其中voidMethod没有参数也可以。
It's a bit longer than what you started with, but this does what you asked for... and a little more besides - for example, callMethod(receiver, "voidMethod") where voidMethod takes no arguments also works.
static void callMethod(Object receiver, String methodName, Object... params) { if (receiver == null || methodName == null) { return; } Class<?> cls = receiver.getClass(); Method[] methods = cls.getMethods(); Method toInvoke = null; methodLoop: for (Method method : methods) { if (!methodName.equals(method.getName())) { continue; } Class<?>[] paramTypes = method.getParameterTypes(); if (params == null && paramTypes == null) { toInvoke = method; break; } else if (params == null || paramTypes == null || paramTypes.length != params.length) { continue; } for (int i = 0; i < params.length; ++i) { if (!paramTypes[i].isAssignableFrom(params[i].getClass())) { continue methodLoop; } } toInvoke = method; } if (toInvoke != null) { try { toInvoke.invoke(receiver, params); } catch (Exception t) { t.printStackTrace(); } } }
更多推荐
带有子类参数的Java getMethod
发布评论