如何使用反射(Java)调用私有静态方法?

如何使用反射(Java)调用私有静态方法?,java,reflection,invoke,Java,Reflection,Invoke,我想调用一个私有静态方法。我有它的名字。我听说它可以使用Java反射机制来完成。我怎么做 EDIT:我在尝试调用该方法时遇到的一个问题是如何指定其参数的类型。我的方法接收一个参数,其类型为Map。因此,我不能执行Map.TYPE(由于Java类型擦除,在运行时没有Map这样的事情)。是否有其他方法获取该方法?假设您想调用MyClass.myMethod(int x) 可能会引发许多已检查的异常。ParameterType和parameters都是椭圆参数(可变长度),请根据需要填写它们。JVMB

我想调用一个私有静态方法。我有它的名字。我听说它可以使用Java反射机制来完成。我怎么做


EDIT:我在尝试调用该方法时遇到的一个问题是如何指定其参数的类型。我的方法接收一个参数,其类型为Map。因此,我不能执行
Map.TYPE
(由于Java类型擦除,在运行时没有Map这样的事情)。是否有其他方法获取该方法?

假设您想调用MyClass.myMethod(int x)

可能会引发许多已检查的异常。ParameterType和parameters都是椭圆参数(可变长度),请根据需要填写它们。JVMBY规范有一个强类型调用约定,因此您需要知道参数类型

话虽如此,除非您正在编写某种应用程序容器、服务器组件容器、类似RMI的系统或基于JVM的语言,否则您应该避免这样做。

Invoke main from

import java.lang.reflect.InvocationTargetException;
导入java.lang.reflect.Method;
导入java.util.array;
公共类调用{
公共静态void main(字符串…参数){
试一试{
Class c=Class.forName(args[0]);
类[]argTypes=新类[]{String[].Class};
方法main=c.getDeclaredMethod(“main”,argTypes);
字符串[]mainArgs=Arrays.copyOfRange(args,1,args.length);
System.out.format(“调用%s.main()%n”,c.getName());
调用(null,(Object)mainArgs);
//生产代码应该更优雅地处理这些异常
}捕获(ClassNotFoundException x){
x、 printStackTrace();
}捕获(NoSuchMethodException x){
x、 printStackTrace();
}捕获(IllegalacessException x){
x、 printStackTrace();
}捕获(调用TargetException x){
x、 printStackTrace();
}
}
}

不,你不能说
Map.class
。这是因为类型擦除。在运行时,没有这样的事情

幸运的是,您可以简单地说是老的
Map.class
。在运行时都是一样的


如果警告让您感到困扰,请搜索与泛型和类型擦除相关的其他问题,这里有大量关于该主题的信息。

我使用一个方法封装获取目标方法,然后调用它。当然,可能有一些限制。下面是放入类及其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));

    }
}
公共类调用程序{
/**
*获取方法并调用它。
* 
*@作者jbetancourt
* 
*@param方法的名称
*@param obj对象调用上的方法
*@param-types方法的参数类型
*@param args到方法调用
*@返回值
*@对不可见的东西抛出异常
*/
公共静态最终对象invokeMethod(最终字符串名,最终T对象,
最终类[]类型,最终对象…args)引发异常{
方法Method=obj.getClass().getDeclaredMethod(名称、类型);
方法setAccessible(true);
返回方法.invoke(obj,args);
}
/**
*嵌入式JUnit测试。
*/
@RunWith(JUnit4.class)
公共静态类调用测试{
/** */
@试验
public void testInvoke()引发异常{
类TestTarget{
私有字符串hello(){
返回“你好,世界!”;
}
}
String actual=(String)Invoker.invokeMethod(“你好”,
新TestTarget(),新类[]{});
字符串应为=“你好,世界!”;
(实际的、预期的)资产;
}
}

}

谢谢。我的方法接收一个参数,其类型为Map。因此,我无法执行“Map.TYPE”。还有别的方法可以得到这个方法吗?@snakile:try
MyClass.class.getDeclaredMethod(“myMethod”,Map.class)
对于您的案例,如何更改(类、字符串等)。type?@deliver通常您可以使用
YourClass.class
作为参数,
Integer.type
只是基本类型的支柱,它们没有真正的类。但是,您如何获得该方法的返回值呢?因为它是静态的,所以不会保存在
o
对于您的案例,有趣的是,该方法的通用信息在运行时仍然可用<代码>方法。getGenericParameterTypes
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
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();
    }
    }
}
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));

    }
}