I have a question regarding method.invoke(). I'm constructing method with following code:
public void exec(String property_name, Object value){
try{
Method method = some_class.getClass().
getMethod("set"+property_name, new Class[] {
value.getClass()
}
);
method.invoke(some_class, value);
}catch(Exception e){
e.printStackTrace();
}
}
My some_class has method:
public void setA(Test test){
// do something
}
The parameter of the setA function is interface and looks like:
public interface Test{
public void write(String str);
}
When I use exec() function from the first example code with TestImpl which is implementation of Test, exception is being raised, notifying that method not found in some_class. But when I use the function exec() with original class and not an extension or implementation, method exec() works fine.
What should I do for method to work with implementations of class?
Update with SSCCE in case it's needed by some1:
public class test {
public static void main(String[] args) {
exec("Name", new TestClassImpl());
}
public static void exec(String property_name, Object value){
try{
some_class sc = new some_class();
Method method = sc.getClass().
getMethod("set"+property_name, new Class[] {
开发者_如何学运维 value.getClass()
}
);
method.invoke(sc, value);
}catch(Exception e){
e.printStackTrace();
}
}
}
class some_class{
public some_class(){}
public void setName(TestClass test){
System.out.println(test.name());
}
}
interface TestClass{
public String name();
}
class TestClassImpl implements TestClass{
public String name() {
return "sscce";
}
}
Thanks in advance, Serhiy.
The problem is the new Class[] { value.getClass() }
. With this you search for a method with exactly the same class as parameter type, which does not exist.
Try this:
for (PropertyDescriptor prop : Introspector.getBeanInfo(some_class.getClass()).getPropertyDescriptors()) {
if (prop.getName().equals(property_name)) {
prop.getWriteMethod().invoke(some_class, value)
}
}
or just use Class.getMethods()
and search for setter name and one arg.
In the general case, this isn't easy. Your getting into parts of the Java spec that even most compilers don't get exactly right.
In this special case (exactly one parameter), you basically have to find a method whose parameter type is compatible with the type of the given argument. Either walk up the inheritance hierarchy of the argument type (don't forget multiple interfaces!), or go through all methods of the class that have one parameter and the required name and check paramType.isAssignableFrom(argType).
There's a utility class in Spring that probably gets it right for most cases:
http://springframework.cvs.sourceforge.net/viewvc/springframework/spring/src/org/springframework/util/MethodInvoker.java?view=markup#l210
(Not sure if this is the latest version of the class.)
精彩评论