1

I am using the getMethod(String name, Class[] types) method to get a method but I get a method not found when there is an int parameter. I think I get that because inside my Class array I have the java.lang.Integer class (the wrapper) instead of int. I get that class by using a generic Object.getClass() so I don't think I can change that easily. Here is the part of the code that does this:

for (int i = 0; i < parameterTypes.length; i++) {
        parameterTypes[i] = arguments[i].getClass();
}

try {
    Method mmethod = mclass.getMethod(contractName, parameterTypes);
} catch (NoSuchMethodException e) {}

Can I solve this somehow?

mousi
  • 248
  • 3
  • 14

2 Answers2

3

Suppose you have this class

class ReflectTest {
    Object o = null;
    public void setO(int i) {
        System.out.println("set int");
        o = i;
    }
    public void setO(Integer i) {
        System.out.println("set Integer");
        o = i;
    }
}

setO(int i) and setO(Integer i) are two different methods, so you cannot have only one of them in your class and rely on autoboxing to get the method object via Class#getMethod(Class<?>...) and passing one or the other argument type.

@Test
public void invoke() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    Method method = ReflectTest.class.getMethod("setO", int.class);
    method.invoke(new ReflectTest(), 3);
    method.invoke(new ReflectTest(), Integer.valueOf(3));

    method = ReflectTest.class.getMethod("setO", Integer.class);
    method.invoke(new ReflectTest(), 3);
    method.invoke(new ReflectTest(), Integer.valueOf(3));
}

will both print

set int
set int

and

set Integer
set Integer

Here autoboxing works on invokation.

But in you case you extract the type of the argument from a value which is stored as Object. In this case primitive types are autoboxed into theire respective wrapper types, hence you do not find a method which corresponds to int.class as argument.

@Test
public void invoke() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    invoke(new ReflectTest(), "setO", 3);
    invoke(new ReflectTest(), "setO", Integer.valueOf(3));
}

private void invoke(Object instance, String methodeName, Object argValue) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    System.out.println(argValue.getClass().isPrimitive());
    Method method = ReflectTest.class.getMethod("setO", argValue.getClass());
    method.invoke(new ReflectTest(), argValue);
    method.invoke(new ReflectTest(), Integer.valueOf(3));
}

Here the output is:

false
set Integer
false
set Integer

As you see, no primitives and only the method with Integer.class is found and called. If you remove it you will get NoSuchMethodException.

So to solve your problem change the method your are trying to invoke via reflection to take a wrapper type or better yet, pass the correct argument types instead of deriving them from some values.

Finally, NoSuchMethodException is also thrown when the method is not accessible i.e. not public, make sure the method is public.

A4L
  • 17,353
  • 6
  • 49
  • 70
0

As per this question, you should use Integer.TYPE to refer to the primitive int for reflection purposes.

Community
  • 1
  • 1
hugh
  • 2,237
  • 1
  • 12
  • 25