[英]How do I invoke a private static method using reflection (Java)?
I would like to invoke a private static method. 我想调用一个私有静态方法。 I have its name.
我有它的名字。 I've heard it can be done using Java reflection mechanism.
我听说可以使用Java反射机制完成它。 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.
我的方法接收一个参数,其类型是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). 因此我不能做
Map<User, String>.TYPE
(在运行时因为Java Type擦除而没有Map这样的东西)。 Is there another way to get the method? 有没有其他方法来获得该方法?
Let's say you want to call MyClass.myMethod(int x); 假设您要调用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
Invoke main from reflection tutorial 从反射教程调用main
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();
}
}
}
No, you can't say Map<K,V>.class
. 不,你不能说
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
. 幸运的是,你可以说只是简单的旧
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. 如果警告困扰您,请搜索与泛型和类型擦除相关的其他问题,这里有关于该主题的大量信息。
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:
这是放入类的方法及其JUnit测试:
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));
}
}
} }
Object insecure; //This needs to be an initialized reference
Class c = insecure.getClass();
Method m = c.getMethod(name, parameterTypes); //Fill the name and types in
m.setAccessible(true);
m.invoke( insecure, parameters ); //Fill in the parameters you would like
There are a number of checked exceptions which may be thrown. 可能会抛出许多经过检查的异常。 Both parameterTypes and parameters are ellipse arguments (variable length), fill them in as needed.
参数类型和参数都是椭圆形参数(可变长度),根据需要填充它们。 The JVM by specification has a strongly typed calling convention so you need to know the parameter types.
规范的JVM具有强类型调用约定,因此您需要知道参数类型。
With that said, unless you are writing some sort of application container, server component container, RMI-like system, or JVM based langauge you should avoid doing this. 话虽如此,除非您正在编写某种应用程序容器,服务器组件容器,类似RMI的系统或基于JVM的语言,否则您应该避免这样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.