【问题标题】:Using reflection to get a method; method parameters of interface types aren't found使用反射获取方法;找不到接口类型的方法参数
【发布时间】:2011-04-05 20:51:54
【问题描述】:

当参数类型为接口时,如何根据参数值获取使用反射的方法?

在以下情况下(基于this example),newValue 将是称为fooList<String>。所以我会打电话给addModelProperty("Bar", foo); 但这仅适用于我不使用界面且仅使用LinkedList<String> foo 的情况。如何使用newValue 的接口并从model 获取具有接口作为参数addBar(List<String> a0) 的方法?

public class AbstractController {
  private final AbstractModel model;
  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) {}
  }
  private Method getMethod(Class clazz, String name, Object parameter) {
    return clazz.getMethod(name, parameter.getClass());
  }
}

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

【问题讨论】:

  • 为什么不发布您尝试过但不起作用的代码,以便我们了解您希望它如何工作?

标签: java methods reflection interface subclass


【解决方案1】:

实际上,您必须搜索模型中的所有方法,并找到与您拥有的参数兼容的方法。有点乱,因为一般来说,可能还有更多。

如果您只对公共方法感兴趣,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. */

【讨论】:

  • 我们不能将它用于私有方法
  • @HendraWD 没错。对于私有方法,需要使用getDeclaredMethods()列出方法,如果没有找到该方法,则必须在父类上重复该过程,以此类推。
【解决方案2】:

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

如果您介意添加此依赖项,您至少会发现查看how this method is implemented 很有用。

【讨论】:

    【解决方案3】:

    Another answer 建议使用 Apache Commons 来获取使用 MethodUtils.getMatchingAccessibleMethodMethod 对象。

    但是,除了立即在实例上调用它之外,您似乎没有将Method 对象用于其他任何事情。在这种情况下,您可以改用 Apache Commons Lang 的 MethodUtils.invokeMethod(Object object, String methodName, Object... args)。这不仅仅是返回 Method 对象,而是调用给定对象的方法。

    protected void addModelProperty(String propertyName, Object newValue) {
      try {
        MethodUtils.invokeMethod(model, "add" + propertyName, newValue);
      } catch (ReflectiveOperationException e) {
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-25
      • 2011-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多