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

Reflection - Getting different results from HashMap - LinkedHashMap

我会保持简短,我有一个 Dog class 如下所示:

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 CallWrong Call 输出。

我需要确保每次放置 "foo" 键时,它必须调用 Foo() 方法,而不是 Boo().

显然,它并没有缓解我的 "method call" 问题。我怎样才能克服这个问题?我必须每次都调用正确的方法。我对这种反射的东西很陌生,有什么我不应该做的,或者我做错了什么吗?或者有没有更好的方法来实现这个方法调用?

编辑:我也试过 LinkedHashMap,但是结果是一样的。

谢谢。

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

来自 Class.getMethods() 的 javadoc:

The elements in the array returned are not sorted and are not in any particular order.

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

的方法

也就是说,Reflection 可能不是您正在尝试完成的工作的正确工具。你应该在更高的层次上解释你想做什么,以及为什么你认为使用反射是个好主意。通常情况下,它不是。

据我所知,这与将方法放入地图无关 - 您可以完全删除地图部分,但仍然面临同样的问题:

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() 没有按照您应该依赖的顺序 return 来自 class 的方法。如果你想专门调用你的 Foo 方法(应该是 foo 以遵循 Java 命名约定),你可能应该使用 Class.getMethod("foo") 来获取方法 按名字.

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

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

此代码显然缺少所有 try catch 和其他一些东西,但它确实向您展示了重要的一点。您永远不应依赖 getMethods() 中的顺序。相反,如果您知道调用的方法是什么,请始终使用 getMethod 调用按名称获取它。这样,您一定会得到正确的方法。

我认为地图引起了一些转移注意力的问题。

    Dog d = new Dog();
    try {
        d.getClass.getMethod("Foo").invoke(d, null);
    } catch (IllegalAccessException | IllegalArgumentException
            | InvocationTargetException | NoSuchMethodException e) {
        e.printStackTrace();
    }

对此不是百分百确定,但我相信您还需要捕获 NoSuchMethodException。

我会说,除非你只是想了解反射 api,否则我会在使用反射之前三思而后行。在大多数情况下,它不是完成这项工作的正确工具。