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