如何使用reflection(Java)调用私有静态方法?
我想调用一个私有的静态方法。 我有它的名字。 我听说可以使用Javareflection机制来完成。 我该怎么做?
编辑:我试图调用该方法时遇到的一个问题是如何指定其参数的types。 我的方法接收一个参数,其types是Map。 因此,我不能做Map<User, String>.TYPE
(在运行时,因为Java Type擦除,没有Map这样的东西)。 有没有另一种方法来获得该方法?
假设你想调用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
从reflection教程调用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(); } } }
不,你不能说Map<K,V>.class
。 这是因为types擦除 。 在运行时,没有这样的事情。
幸运的是,你可以说只是普通的Map.class
。 运行时完全一样。
如果这些警告打扰了你,寻找与generics和types擦除有关的其他问题,这里有关于这个主题的大量信息。
我使用一个封装获取目标方法的方法,然后调用它。 当然可能有一些限制。 这里是放入类和JUnittesting的方法:
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
有一些可能被抛出的检查exception。 参数types和参数都是椭圆参数(可变长度),根据需要进行填充。 规范中的JVM具有强types的调用约定,因此您需要知道参数types。
这样说,除非你正在编写某种应用程序容器,服务器组件容器,类似RMI的系统或基于JVM的语言,否则你应该避免这样做。