4

I'll keep it brief, I have a Dog class like the following:

public class Dog 
{
   public void Foo() 
   { 
      System.out.println("Right Call");
   }

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

and a main method like following:

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

Whenever I run it again, it just arbitrarily gives Right Call or Wrong Call outputs.

I need to be sure that every time I place the "foo" key, It must to be calling the Foo() method, instead of Boo().

Apparently, It doesn't ease my "method call" problem. How can I overcome this issue? I must be calling the right method every time. I'm quite new to this reflections stuff, is there anything that I shouldn't be doing, or something that I'm doing wrong? Or is there a better way to implement this method calling?

EDIT: I've also tried LinkedHashMap, however, the result is the same.

Thank you.

Radiodef
  • 37,180
  • 14
  • 90
  • 125
Burak.
  • 598
  • 7
  • 19
  • 1
    This doesn't really have anything to do with the HashMap. Use http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getDeclaredMethod%28java.lang.String,%20java.lang.Class...%29 to get the method you actually want instead of [0]. – Adrian Leonhard Apr 07 '15 at 20:57

5 Answers5

8

From the javadoc of Class.getMethods():

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

Yet, your code assumes that the element at index 0 is the method Foo(). Don't make this assumption. Find the method which has the name Foo.

That said, Reflection is probably not the right tool for the job you're trying to do. You should explain, at a higher level, what you're trying to do and why you think using reflection is a good idea. Usually, it's not.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
5

This has nothing to do with putting the method in a map, as far as I can tell - you can remove the map part entirely and still face the same issue:

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

Fundamentally, you're seeing the fact that getMethods() doesn't return the methods from a class in an order you should rely on. If you want to specifically call your Foo method (which should be foo to follow Java naming conventions), you should probably be using Class.getMethod("foo") to get the method by name.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
3

Result of getMethods() is not sorted, so there is no guarantee that method[0] is Foo() (not Boo()). You need to check it before put to map as a value for "foo" key.

dbf
  • 6,399
  • 2
  • 38
  • 65
1

You could off course also use the following reflection:

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

This code is obviously missing all the try catch and some other stuff, but it does show you the important bit. You should never rely on the order in the getMethods(). Instead, if you know what the method is called, always use the getMethod call to get it by name. This way, you're sure to get the correct method.

Ractoc
  • 239
  • 2
  • 9
1

I think the Map has caused a bit of a red herring.

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

Not one hundred percent sure on this, but I believe that you will also need to catch NoSuchMethodException.

I will say, unless you are just trying to learn about the reflection api, I would think twice before using reflection. In most cases, it is not the right tool for the job.

Derek_M
  • 1,018
  • 10
  • 22