60 votes

Comment invoquer une méthode statique privée à l'aide de réflexion (Java)?

Je voudrais invoquer une méthode statique privée. J'ai son nom J'ai entendu dire que cela pouvait être fait en utilisant un mécanisme de réflexion Java. Comment puis-je le faire?

EDIT: Un problème que j'ai rencontré en essayant d'appeler la méthode est de savoir comment spécifier le type de son argument. Ma méthode reçoit un argument et son type est Map. Par conséquent, je ne peux pas faire Map<User, String>.TYPE (au moment de l'exécution, la carte n'existe pas à cause de l'effacement du type Java). Y a-t-il un autre moyen d'obtenir la méthode?

104voto

Landei Points 30509

Supposons que vous souhaitiez appeler 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
 

9voto

Cratylus Points 21838

Invoquer le principal du tutoriel de réflexion

 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();
    }
    }
}
 

2voto

bmargulies Points 49855

Non, vous ne pouvez pas dire Map<K,V>.class . C'est à cause de l' effacement du type . Au moment de l'exécution, il n'y a rien de tel.

Heureusement, vous pouvez tout simplement dire vieux Map.class . C'est pareil au moment de l'exécution.

Si les avertissements vous dérangent, cherchez d'autres questions relatives aux génériques et à l'effacement des types, il existe une mine d'informations sur le sujet ici.

1voto

user167569 Points 71

J'utilise une seule méthode qui encapsule l'obtention de la méthode cible puis son invocation. A probablement des limites, bien sûr. Voici la méthode mise en classe et son 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));

    }
}
 

}

0voto

Mark Points 61
 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
 

Un certain nombre d'exceptions vérifiées peuvent être levées. ParameterTypes et les paramètres sont des arguments ellipse (longueur variable), remplissez-les au besoin. La JVM par spécification a une convention d'appel fortement typée, vous devez donc connaître les types de paramètre.

Cela dit, évitez de procéder de la sorte, sauf si vous écrivez un conteneur d'application, un conteneur de composants de serveur, un système de type RMI ou une langue basée sur JVM.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X