How do I invoke a private static method using reflection (Java)?
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));
}
}
}
snakile
Updated on July 08, 2022Comments
-
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 over 13 yearsThanks. 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 over 13 years@snakile:try
MyClass.class.getDeclaredMethod("myMethod", Map.class);
for your case -
Admin about 8 yearsHow you can change with (class, string, etc. ).type ?
-
Landei about 8 years@delive Usually you can just use
YourClass.class
as argument, theInteger.TYPE
is just a crutch for primitive types, which have no real class. -
Celeritas almost 8 yearsBut then how would you get the return value of the method? Since it's static it won't be saved in
o
. -
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 ofinvoke
). -
Celeritas almost 8 years@Landei then what method do you call on
o
to get the value? -
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 casto
to aString
.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 usesObject
(as some other reflection stuff does as well).