簡體   English   中英

如何使用反射(Java)調用私有靜態方法?

[英]How do I invoke a private static method using reflection (Java)?

我想調用一個私有靜態方法。 我有它的名字。 我聽說可以使用Java反射機制完成它。 我該怎么做?

編輯:嘗試調用方法時遇到的一個問題是如何指定其參數的類型。 我的方法接收一個參數,其類型是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

反射教程調用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 這是因為類型擦除 在運行時,沒有這樣的事情。

幸運的是,你可以說只是簡單的舊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));

    }
}

}

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

可能會拋出許多經過檢查的異常。 參數類型和參數都是橢圓形參數(可變長度),根據需要填充它們。 規范的JVM具有強類型調用約定,因此您需要知道參數類型。

話雖如此,除非您正在編寫某種應用程序容器,服務器組件容器,類似RMI的系統或基於JVM的語言,否則您應該避免這樣做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM