Andrew_CS
Andrew_CS

Reputation: 2562

Java, Reflection, getting a Method from a Class

I'm having some trouble using reflection in Java. I'm attempting to save a method of a data structure but getting an error. The error is

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

The method, in this case, that I'm trying to get is the add method for a SerialList that takes a Comparable and an Object as its parameters.

structType = "cs671.eval.SerialList", keyType = "java.lang.Integer", and valType = "java.lang.String" are strings that were read in from a file.

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){}

Basically I'm trying to get the right method on the right datastructure with the correct classes that are going to get passed into that method but I don't know how to tell the getMethod method that those classes (comparableClass and objectClass) are the correct ones.

Thanks in advance!

Added: Here's the SerialList's add method signature public void add(java.lang.Comparable, java.lang.Object)

Upvotes: 1

Views: 337

Answers (4)

Trevor Freeman
Trevor Freeman

Reputation: 7242

As other answers have stated, to use getMethod() you need to know and use the actual declared formal parameters of the method you are attempting to retrieve.

However, if for some reason you do not know the formal parameters at compile time, then you can iterate over all of the methods from the class until you find a method that fits your parameters (or find the most specific method that fits your parameters).

There is functionality written to do this already in apache commons bean utils, specifically in org.apache.commons.beanutils.MethodUtils.invokeMethod(...) and MethodUtils.getMatchingAccessibleMethod(...).

Source code for the above methods can be easily viewed online here.

Upvotes: 0

anubhava
anubhava

Reputation: 786291

Apologies for providing wrong answer earlier. Based on your comments it appears that you're trying to get a Method by avoiding to provide specific parameter types needed in the signature of that method.

If my understanding is correct then you should rather use Class#getMethods() and examine the returned Method[] for your method. Consider a skeleton code like this:

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
   }
}

Upvotes: 0

Polygnome
Polygnome

Reputation: 7820

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

To find a matching method in a class C: If C declares exactly one public method with the specified name and exactly the same formal parameter types, that is the method reflected. If more than one such method is found in C, and one of these methods has a return type that is more specific than any of the others, that method is reflected; otherwise one of the methods is chosen arbitrarily.

=> You need to pass java.lang.Comparable.class & java.lang.Object.class

Upvotes: 1

Bhesh Gurung
Bhesh Gurung

Reputation: 51030

You are saying -

The method, in this case, that I'm trying to get is the add method for a SerialList that takes a Comparable and an Object as its parameters.

But passing the classes - java.lang.Integer, java.lang.String.


Just a note - Only public methods are visible to getMethod() for non-publics you would have to use getDeclaredMethod() instead.

Upvotes: 5

Related Questions