反射 - 从HashMap和LinkedHashMap中获取不同的结果

4
我简要说明一下,我有一个如下的Dog类:
public class Dog 
{
   public void Foo() 
   { 
      System.out.println("Right Call");
   }

   public void Boo()
   {
     System.out.println("Wrong Call");
   }
}

一个如下所示的主方法:
HashMap<String, Method> map = new HashMap<String, Method>();

Dog d = new Dog();

Method[] method = d.getClass().getMethods();

map.put("foo", method[0]);

Method a = map.get("foo");

try {
    a.invoke(d, null);
} catch (IllegalAccessException | IllegalArgumentException
        | InvocationTargetException e) {
    e.printStackTrace();
}

每次我再次运行它时,它就会随意地输出“Right Call”或“Wrong Call”。
我需要确保每次我放置“foo”键时,它必须调用Foo()方法,而不是Boo()方法。
显然,这并没有解决我的“方法调用”问题。我该如何解决这个问题?我对反射还很陌生,我是否有什么不应该做的事情,或者我做错了什么?还是有更好的实现方法?
编辑:我也尝试过LinkedHashMap,但结果是相同的。
谢谢。

1
这与HashMap实际上没有任何关系。使用http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getDeclaredMethod(java.lang.String,%20java.lang.Class ...)来获取您真正想要的方法,而不是使用[0]。 - Adrian Leonhard
5个回答

8
Class.getMethods()的javadoc中可以看到:

返回的数组元素没有排序,且没有特定顺序。

然而,您的代码假定索引0处的元素是方法Foo()。不要做出这样的假设。请寻找名称为Foo的方法。

话虽如此,反射可能不是你正在尝试完成的任务的正确工具。您应该在更高层次上解释您想要做什么以及为什么认为使用反射是一个好主意。通常情况下,并非如此。


5
这似乎与将方法放入映射中无关 - 您可以完全删除映射部分,仍然面临相同的问题:
Dog d = new Dog();

Method methods = d.getClass().getMethods();        
Method a = methods[0];

try {
    a.invoke(d, null);
} catch (IllegalAccessException | IllegalArgumentException
        | InvocationTargetException e) {
    e.printStackTrace();
}

从根本上说,您正在看到 getMethods() 不以可以依赖的顺序返回类中的方法。如果您想特别调用您的 Foo 方法(应该命名为 foo 以遵循 Java 命名约定),您应该使用 Class.getMethod("foo") 通过名称获取该方法。


3

getMethods() 的结果未排序,因此无法保证 method[0]Foo() 而不是 Boo()。在将其作为“foo”键的值放入映射之前,您需要进行检查。


1
我认为地图引起了一些误导。
    Dog d = new Dog();
    try {
        d.getClass.getMethod("Foo").invoke(d, null);
    } catch (IllegalAccessException | IllegalArgumentException
            | InvocationTargetException | NoSuchMethodException e) {
        e.printStackTrace();
    }

我不是百分之百确定,但我认为您还需要捕获NoSuchMethodException异常。

我要说的是,除非您只是想了解反射API,否则在使用反射之前请三思。在大多数情况下,它并不是最适合此工作的工具。


1

当然,您也可以使用以下的反射:

Dog d = new Dog();
map.put("foo", d.getClass().getMethod("Foo");
Method m = map.get("foo");
m.invoke()

这段代码显然缺少所有的try catch以及其他一些东西,但它确实向你展示了重要的部分。您不应该依赖于getMethods()中的顺序。相反,如果您知道方法的名称,请始终使用getMethod调用按名称获取它。这样,您可以确保获取正确的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接