initialZero initialZero - 1 month ago 14
Java Question

Using reflection to get a method; method parameters of interface types aren't found

Maybe I'm missing something simple here but how do I get a method whose parameter is an interface using reflection.

In the following case

newValue
would be a
List<String>
called
foo
. So I would call
addModelProperty("Bar", foo);
But this only works for me if I don't use the interface and only use
LinkedList<String> foo
. How do I use an interface for
newValue
and get the method from
model
that has an interface as the parameter
addBar(List<String> a0)
?

Here is a more detailed example. (based on: This example)

public class AbstractController {
public setModel(AbstractModel model) {
this.model = model;
}
protected void addModelProperty(String propertyName, Object newValue) {
try {
Method method = getMethod(model.getClass(), "add" + propertyName, newValue);
method.invoke(model, newValue);
} catch (NoSuchMethodException e) {
} catch (InvocationTargetException e) {
} catch (Exception e) {}
}
}

public class AbstractModel {
protected PropertyChangeSupport propertyChangeSupport;
protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
}
}

public class Model extends AbstractModel {
public void addList(List<String> list) {
this.list.addAll(list);
}
}

public class Controller extends AbstractController {
public void addList(List<String> list) {
addModelProperty(list);
}
}

public void example() {
Model model = new Model();
Controller controller = new Controller();
List<String> list = new LinkedList<String>();
list.add("example");
// addList in the model is only found if LinkedList is used everywhere instead of List
controller.addList(list);
}

Answer

You'll actually have to search through all the methods in your model and find those that are compatible with the arguments you have. It is a bit messy, because, in general, there might be more that one.

If you are interested in just public methods, the getMethods() method is the easiest to use, because it gives you all accessible methods without walking the class hierarchy.

Collection<Method> candidates = new ArrayList<Method>();
String target = "add" + propertyName;
for (Method m : model.getClass().getMethods()) {
  if (target.equals(m.getName())) {
    Class<?>[] params = m.getParameterTypes();
    if (params.length == 1) {
      if (params[0].isInstance(newValue))
        candidates.add(m);
    }
  }
}
/* Now see how many matches you have... if there's exactly one, use it. */