java 使用反射获取方法;找不到接口类型的方法参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3602413/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 02:36:40  来源:igfitidea点击:

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

javareflection

提问by initialZero

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 newValuewould 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 newValueand get the method from modelthat has an interface as the parameter addBar(List<String> a0)?

在以下情况下newValue将是一个List<String>被调用的foo. 所以我会打电话,addModelProperty("Bar", foo);但这只对我有用,如果我不使用接口并且只使用LinkedList<String> foo. 如何使用接口newValue并从中获取model具有接口作为参数的方法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);
}

回答by erickson

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.

如果您只对公共方法感兴趣,那么该getMethods()方法最容易使用,因为它为您提供了所有可访问的方法,而无需遍历类层次结构。

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. */

回答by Lodovik

If you don't mind adding a dependency to Apache Commons, you may use MethodUtils.getMatchingAccessibleMethod(Class clazz, String methodName, Class[] parameterTypes).

如果您不介意向 Apache Commons 添加依赖项,您可以使用MethodUtils.getMatchingAccessibleMethod(Class clazz, String methodName, Class[] parameterTypes).

If you mind adding this dependency, you may at least find it useful to take a look at how this method is implemented.

如果您介意添加此依赖项,那么您至少会发现查看此方法是如何实现的很有用。