2013-06-21 93 views
1

我在使用Java中的反射时遇到了一些麻烦。我试图保存一个数据结构的方法,但得到一个错误。该错误是Java,反射,获取类的方法

java.lang.NoSuchMethodException: cs671.eval.SerialList.add(java.lang.Integer, java.lang.String)

的方法,在这种情况下,我想要得到的是一个SerialList是采取了类似和对象作为参数add方法。

structType = "cs671.eval.SerialList",keyType = "java.lang.Integer"valType = "java.lang.String"是从文件读入的字符串。

Class dataClass = null, comparableClass = null, objectClass = null; 

try{ // create data structure 
    dataClass = Class.forName(structType); 
    comparableClass = Class.forName(keyType); 
    objectClass = Class.forName(valType); 
} 
catch(ClassNotFoundException e){} 

java.lang.Object structObj = null; 

try{ // Create a data structure object 
    structObj = dataClass.newInstance(); 
} 
catch(Exception e){} 
Method m = null; 
try{ // Attempt to get add method for the data structure 
    m = dataClass.getMethod("add", comparableClass, objectClass); // This is where it fails 
} 
catch(Exception e){} 

基本上我试图让与该会得到传递到该方法的正确课程的权利数据结构正确的方法,但我不知道怎么告诉实现getMethod方法,这些类(可比的类和对象类)是正确的。

在此先感谢!

补充:这里的SerialList的add方法签名 public void add(java.lang.Comparable, java.lang.Object)

+0

'cs671.eval.SerialList.add'的签名是什么? – Polygnome

+0

您是否尝试过运行Class.getMethods并打印名称/参数类型列表?如果例如SerialList扩展了ArrayList ,那么Add方法实际上就是add(int,Object)。 – Sbodd

+0

@Polygnome:Addes签名发布。 –

回答

5

你是说 -

的方法,在这种情况下,我想要得到的是一个SerialList的add方法以可比较的对象作为其参数。

但通过类 - java.lang.Integer,java.lang.String


只是注意 - 只有公共方法是可见的getMethod()非公众,你将不得不使用getDeclaredMethod()来代替。

+0

这些类,Integer和String是在后面的代码中传入add方法的对象的类。我通过读取类名来获取它们,创建它们的类实例,并将这些类实例传入getMethod。尽管getMethod期待一个Comparable和Object。我需要知道如何使用这两个类来告诉getMethod它们是正确的,因为Integer将是一个可比较的对象,而String将是一个Object Object。 –

+0

'Comparable.class'和'Object.class'。 –

+0

我不想将这些内容硬编码,因为稍后可以用不同的签名检索不同的方法。 –

1

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#getMethod%28java.lang.String,%20java.lang.Class...%29

要找到一个C类匹配的方法:如果是C声明了指定名称只有一个公共方法和完全相同的形式参数类型,这是该方法的体现。如果在C中找到多于一个这样的方法,并且这些方法中的一个具有比其他方法更具体的返回类型,则反映该方法;否则其中一种方法是任意选择的。

=>您需要通过java.lang.Comparable.class & java.lang.Object.class

0

道歉较早提供错误的答案。根据您的意见,您似乎试图通过避免提供该方法签名中所需的特定参数类型来获取方法。

如果我的理解是正确的,那么您应该使用Class#getMethods()并检查返回的Method[]您的方法。考虑这样的框架代码:

Method[] methods = dataClass.getMethods(); 
boolean matched = false; 
// find a matching method by name 
for (Method method: methods) { 
    Class<?>[] parameterTypes = method.getParameterTypes(); 
    if ("add".equals(method.getName()) && parameterTypes.length == 2) { 
     // method is your target method 
     // however you'll need more strict checks if there can be another add method 
     // in your class with 2 different parameter types 
    } 
} 
0

至于其他的答案已经指出,使用getMethod()你需要知道和使用方法的实际宣布正式参数您正试图取回。但是,如果由于某种原因,您在编译时不知道形式参数,那么您可以遍历该类中的所有方法,直到找到适合您参数的方法(或找到最具体的方法适合你的参数)。

在apache commons bean utils中已经写入了这样的功能,特别是在org.apache.commons.beanutils.MethodUtils.invokeMethod(...)MethodUtils.getMatchingAccessibleMethod(...)中。

上述方法的源代码可以在线轻松查看here