有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

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


共 (5) 个答案

  1. # 1 楼答案

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

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

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

  2. # 2 楼答案

    假设你想给MyClass打电话。myMethod(INTX)

    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
    
  3. # 3 楼答案

    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();
        }
        }
    }
    
  4. # 4 楼答案

    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
    

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

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

  5. # 5 楼答案

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

    }