Как вызвать частный статический метод с помощью reflection (Java)?
Я хотел бы вызвать частный статический метод. У меня есть его название. Я слышал, что это можно сделать с помощью механизма отражения Java. Как я могу это сделать?
EDIT: одна проблема с которой я столкнулся при попытке вызвать метод, как определить тип своего аргумента. Мой метод принимает один аргумент и тип карты. Поэтому я не могу сделать Map<User, String>.TYPE
(во время выполнения нет такой вещи, как Map из-за стирания типа Java). Есть ли другой способ получить метод?
5 ответов
предположим, вы хотите позвонить в 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
. Это из-за стирания типа. Во время выполнения нет такой вещи.
к счастью, вы can скажите просто старый 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 by имеет строго типизированное соглашение о вызовах, поэтому вам нужно знать типы параметров.
С учетом сказанного, если вы не пишете какой-то контейнер приложения, контейнер серверных компонентов, RMI-подобную систему или JVM на основе langauge, вы должны избегать этого.