Как мне вызвать метод Java, если имя метода задано в виде строки?
Если у меня есть две переменные:
Object obj;String methodName = "getName";
Не зная класса obj, как я могу вызвать в нем метод, идентифицированный с помощью methodName?
obj
methodName
Вызываемый метод не имеет параметров и String возвращает значение. Это средство получения для Java bean.
String
Переведено автоматически
Ответ 1
Кодирование с нуля, это было бы что-то вроде:
java.lang.reflect.Method method;try { method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);} catch (SecurityException e) { ... } catch (NoSuchMethodException e) { ... }
Параметры определяют очень конкретный метод, который вам нужен (если доступно несколько перегруженных методов, если у метода нет аргументов, только укажите methodName).
Затем вы вызываете этот метод, вызывая
try { method.invoke(obj, arg1, arg2,...);} catch (IllegalArgumentException e) { ... } catch (IllegalAccessException e) { ... } catch (InvocationTargetException e) { ... }
Опять же, не указывайте аргументы в .invoke, если у вас их нет. Но да. Почитайте о отражении Java
.invoke
Ответ 2
Используйте вызов метода из отражения:
Class<?> c = Class.forName("class name");Method method = c.getDeclaredMethod("method name", parameterTypes);method.invoke(objectToInvokeOn, params);
Где:
"class name"
objectToInvokeOn
"method name"
parameterTypes
Class[]
params
Object[]
Ответ 3
Для тех, кому нужен простой пример кода на Java 7:
Dog класс:
Dog
package com.mypackage.bean;public class Dog { private String name; private int age; public Dog() { // empty constructor } public Dog(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void printDog(String name, int age) { System.out.println(name + " is " + age + " year(s) old."); }}
ReflectionDemo класс:
ReflectionDemo
package com.mypackage.demo;import java.lang.reflect.*;public class ReflectionDemo { public static void main(String[] args) throws Exception { String dogClassName = "com.mypackage.bean.Dog"; Class<?> dogClass = Class.forName(dogClassName); // convert string classname to class Object dog = dogClass.newInstance(); // invoke empty constructor String methodName = ""; // with single parameter, return void methodName = "setName"; Method setNameMethod = dog.getClass().getMethod(methodName, String.class); setNameMethod.invoke(dog, "Mishka"); // pass arg // without parameters, return string methodName = "getName"; Method getNameMethod = dog.getClass().getMethod(methodName); String name = (String) getNameMethod.invoke(dog); // explicit cast // with multiple parameters methodName = "printDog"; Class<?>[] paramTypes = {String.class, int.class}; Method printDogMethod = dog.getClass().getMethod(methodName, paramTypes); printDogMethod.invoke(dog, name, 3); // pass args }}
Вывод:Mishka is 3 year(s) old.
Mishka is 3 year(s) old.
Вы можете вызвать конструктор с параметрами таким образом:
Constructor<?> dogConstructor = dogClass.getConstructor(String.class, int.class);Object dog = dogConstructor.newInstance("Hachiko", 10);
В качестве альтернативы вы можете удалить
String dogClassName = "com.mypackage.bean.Dog";Class<?> dogClass = Class.forName(dogClassName);Object dog = dogClass.newInstance();
и выполнить
Dog dog = new Dog();Method method = Dog.class.getMethod(methodName, ...);method.invoke(dog, ...);
Рекомендуемое чтение: Создание новых экземпляров класса
Ответ 4
Метод может быть вызван следующим образом. Есть и другие возможности (проверьте reflection api), но это самая простая из них:
import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import org.junit.Assert;import org.junit.Test;public class ReflectionTest { private String methodName = "length"; private String valueObject = "Some object"; @Test public void testGetMethod() throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { Method m = valueObject.getClass().getMethod(methodName, new Class[] {}); Object ret = m.invoke(valueObject, new Object[] {}); Assert.assertEquals(11, ret); }}