How do I invoke a private static method using reflection (Java)?

55,683

Solution 1

Let's say you want to call MyClass.myMethod(int x);

Method m = MyClass.class.getDeclaredMethod("myMethod", Integer.TYPE);
m.setAccessible(true); //if security settings allow this
Object o = m.invoke(null, 23); //use null if the method is static

Solution 2

Invoke main from reflection tutorial

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

public class InvokeMain {
    public static void main(String... args) {
    try {
        Class<?> c = Class.forName(args[0]);
        Class[] argTypes = new Class[] { String[].class };
        Method main = c.getDeclaredMethod("main", argTypes);
        String[] mainArgs = Arrays.copyOfRange(args, 1, args.length);
        System.out.format("invoking %s.main()%n", c.getName());
        main.invoke(null, (Object)mainArgs);

        // production code should handle these exceptions more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    } catch (NoSuchMethodException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    } catch (InvocationTargetException x) {
        x.printStackTrace();
    }
    }
}

Solution 3

No, you can't say Map<K,V>.class. This is because of type erasure. At runtime, there's no such thing.

Luckily, you can say just plain old Map.class. It's all the same at runtime.

If the warnings bother you, search for other questions related to generics and type erasure, there's a wealth of information on the subject here.

Solution 4

I use a single method that encapsulates getting the target method and then invoking it. Probably has some limitations, of course. Here is the method put into a class and its JUnit test:

public class Invoker {
/**
 * Get method and invoke it.
 * 
 * @author jbetancourt
 * 
 * @param name of method
 * @param obj Object to invoke the method on
 * @param types parameter types of method
 * @param args to method invocation
 * @return return value
 * @throws Exception for unforseen stuff
 */
public static final <T> Object invokeMethod(final String name, final T obj,
  final Class<?>[] types, final Object... args) throws Exception {

    Method method = obj.getClass().getDeclaredMethod(name, types);
    method.setAccessible(true);
    return method.invoke(obj, args);
}

/**
 * Embedded JUnit tests.
 */
@RunWith(JUnit4.class)
public static class InvokerTest {
    /** */
    @Test
    public void testInvoke() throws Exception {
        class TestTarget {
            private String hello() {
                return "Hello world!";
            }
        }

        String actual = (String) Invoker.invokeMethod("hello",
                new TestTarget(), new Class<?>[] {});
        String expected = "Hello world!";
        assertThat(actual, is(expected));

    }
}

}

Share:
55,683
snakile
Author by

snakile

Updated on July 08, 2022

Comments

  • snakile
    snakile almost 2 years

    I would like to invoke a private static method. I have its name. I've heard it can be done using Java reflection mechanism. How can I do it?

    EDIT: One problem I encountered when trying to invoke the method is how to specify the type of its argument. My method receives one argument and its type is Map. Therefore I cannot do Map<User, String>.TYPE (In run time there's no such a thing as Map because of Java Type erasure). Is there another way to get the method?

  • snakile
    snakile over 13 years
    Thanks. My method receives one parameter and its type is Map<User, String>. Therefore I cannot do 'Map<User, String>.TYPE'. Is there another way to get the method?
  • Cratylus
    Cratylus over 13 years
    @snakile:try MyClass.class.getDeclaredMethod("myMethod", Map.class); for your case
  • Admin
    Admin about 8 years
    How you can change with (class, string, etc. ).type ?
  • Landei
    Landei about 8 years
    @delive Usually you can just use YourClass.class as argument, the Integer.TYPE is just a crutch for primitive types, which have no real class.
  • Celeritas
    Celeritas almost 8 years
    But then how would you get the return value of the method? Since it's static it won't be saved in o.
  • Landei
    Landei almost 8 years
    @Celeritas The return value should be in o, this is not the object you're calling it on (if you had an object, it needs to be the first argument of invoke).
  • Celeritas
    Celeritas almost 8 years
    @Landei then what method do you call on o to get the value?
  • Landei
    Landei almost 8 years
    @Celeritas It is the value, you just need to cast it. E.g. if your static method returns a String, you can cast o to a String. Method.invoke must be able to return values from all kinds of methods, so which return type should it use in its method declaration? It can't know the type, so it uses Object (as some other reflection stuff does as well).