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

发布于 2024-09-16 12:54:31 字数 2015 浏览 6 评论 0原文

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

在以下情况下(基于此示例),newValue 将是一个名为 fooList。所以我会调用 addModelProperty("Bar", foo); 但这仅适用于我不使用接口而仅使用 LinkedList; foo.如何使用 newValue 的接口并从具有接口作为参数 addBar(Lista0)model 获取方法?

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

How do I get a method using reflection based on a parameter value when the parameter type is an interface?

In the following case (based on this example), 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)?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

日裸衫吸 2024-09-23 12:54:31

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

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

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. */
裂开嘴轻声笑有多痛 2024-09-23 12:54:31

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

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

If you don't mind adding a dependency to Apache Commons, you may use 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.

清眉祭 2024-09-23 12:54:31

另一个答案建议使用 Apache Commons 使用 MethodUtils.getMatchingAccessibleMethod< 获取 Method 对象/代码>。

但是,看起来您除了立即在实例上调用 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) {
  }
}

Another answer suggested using Apache Commons to get the Method object using MethodUtils.getMatchingAccessibleMethod.

However, it looks like you're not using the Method object for anything other than immediately invoking it on an instance. This being the case, you can instead use Apache Commons Lang's MethodUtils.invokeMethod(Object object, String methodName, Object... args). Rather than just returning the Method object, this instead invokes the method on the given object.

protected void addModelProperty(String propertyName, Object newValue) {
  try {
    MethodUtils.invokeMethod(model, "add" + propertyName, newValue);
  } catch (ReflectiveOperationException e) {
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文