Как вызвать метод Java, когда имя метода называется строкой?
Если у меня есть две переменные:
Object obj;
String methodName = "getName";
Не зная класса obj
, как я могу назвать метод, идентифицированный methodName
на нем?
Вызываемый метод не имеет параметров и возвращает значение String
. Это геттер для Java bean.
Ответы
Ответ 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 Reflection
Ответ 2
Использовать отражение:
http://java.sun.com/docs/books/tutorial/reflect/member/methodInvocation.html
Class<?> c = Class.forName("class name");
Method method = c.getDeclaredMethod ("method name", parameterTypes)
method.invoke (objectToInvokeOn, params)
Где:
"имя класса" - это имя класса
objectToInvokeOn имеет тип Object и является объектом, который вы хотите вызвать метод на
"имя метода" - это имя метода, который вы хотите вызвать
parameterTypes имеет тип Class [] и декалит параметры, которые принимает метод
params имеет тип Object [] и объявляет параметры, которые должны быть переданы методу
Ответ 3
Для тех, кому нужен пример прямого кода в Java 7:
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
класс:
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.
Вы можете вызвать конструктор с параметрами таким образом:
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();
и do
Dog dog = new Dog();
Method method = Dog.class.getMethod(methodName, ...);
method.invoke(dog, ...);
Рекомендуемое чтение: Создание новых экземпляров класса
Ответ 4
Этот метод можно вызвать следующим образом. Есть также больше возможностей (проверьте отражение 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);
}
}
Ответ 5
Во-первых, не надо. Избегайте такого кода. Это также очень плохой код и небезопасный (см. Раздел 6 Правила безопасного кодирования для
Язык программирования Java, версия 2.0).
Если вы должны это сделать, предпочитайте java.beans для размышлений. Beans обтекает отражение, обеспечивая относительно безопасный и обычный доступ.
Ответ 6
Чтобы заполнить мои ответы коллег, вы можете обратить пристальное внимание на:
- статические вызовы или вызовы экземпляров (в одном случае вам не нужен экземпляр класса, в другом случае вам может потребоваться использовать существующий конструктор по умолчанию), который может быть или не быть )
- вызов общедоступного или непубличного метода (для последнего вам нужно вызвать setAccessible для метода в пределах doPrivileged block, другой findbugs не будут счастливы)
- инкапсулируя еще одно управляемое исключение для приложения, если вы хотите отбросить многочисленные исключения системы Java (следовательно, CCException в коде ниже)
Вот старый код java1.4, который учитывает эти моменты:
/**
* Allow for instance call, avoiding certain class circular dependencies. <br />
* Calls even private method if java Security allows it.
* @param aninstance instance on which method is invoked (if null, static call)
* @param classname name of the class containing the method
* (can be null - ignored, actually - if instance if provided, must be provided if static call)
* @param amethodname name of the method to invoke
* @param parameterTypes array of Classes
* @param parameters array of Object
* @return resulting Object
* @throws CCException if any problem
*/
public static Object reflectionCall(final Object aninstance, final String classname, final String amethodname, final Class[] parameterTypes, final Object[] parameters) throws CCException
{
Object res;// = null;
try {
Class aclass;// = null;
if(aninstance == null)
{
aclass = Class.forName(classname);
}
else
{
aclass = aninstance.getClass();
}
//Class[] parameterTypes = new Class[]{String[].class};
final Method amethod = aclass.getDeclaredMethod(amethodname, parameterTypes);
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
amethod.setAccessible(true);
return null; // nothing to return
}
});
res = amethod.invoke(aninstance, parameters);
} catch (final ClassNotFoundException e) {
throw new CCException.Error(PROBLEM_TO_ACCESS+classname+CLASS, e);
} catch (final SecurityException e) {
throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_SECURITY_ISSUE, e);
} catch (final NoSuchMethodException e) {
throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_NOT_FOUND, e);
} catch (final IllegalArgumentException e) {
throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_ILLEGAL_ARGUMENTS+String.valueOf(parameters)+GenericConstants.CLOSING_ROUND_BRACKET, e);
} catch (final IllegalAccessException e) {
throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_ACCESS_RESTRICTION, e);
} catch (final InvocationTargetException e) {
throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_INVOCATION_ISSUE, e);
}
return res;
}
Ответ 7
//Step1 - Using string funClass to convert to class
String funClass = "package.myclass";
Class c = Class.forName(funClass);
//Step2 - instantiate an object of the class abov
Object o = c.newInstance();
//Prepare array of the arguments that your function accepts, lets say only one string here
Class[] paramTypes = new Class[1];
paramTypes[0]=String.class;
String methodName = "mymethod";
//Instantiate an object of type method that returns you method name
Method m = c.getDeclaredMethod(methodName, paramTypes);
//invoke method with actual params
m.invoke(o, "testparam");
Ответ 8
Object obj;
Method method = obj.getClass().getMethod("methodName", null);
method.invoke(obj, null);
Ответ 9
Это похоже на то, что можно сделать с пакетом Java Reflection.
http://java.sun.com/developer/technicalArticles/ALT/Reflection/index.html
В частности, под Вызов методов по имени:
импортировать java.lang.reflect. *;
public class method2 {
public int add(int a, int b)
{
return a + b;
}
public static void main(String args[])
{
try {
Class cls = Class.forName("method2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Method meth = cls.getMethod(
"add", partypes);
method2 methobj = new method2();
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj
= meth.invoke(methobj, arglist);
Integer retval = (Integer)retobj;
System.out.println(retval.intValue());
}
catch (Throwable e) {
System.err.println(e);
}
}
}
Ответ 10
Если вы выполняете вызов несколько раз, вы можете использовать новые дескрипторы методов, введенные в Java 7. Здесь мы переходим к тому, чтобы ваш метод возвращал строку:
Object obj = new Point( 100, 200 );
String methodName = "toString";
Class<String> resultType = String.class;
MethodType mt = MethodType.methodType( resultType );
MethodHandle methodHandle = MethodHandles.lookup().findVirtual( obj.getClass(), methodName, mt );
String result = resultType.cast( methodHandle.invoke( obj ) );
System.out.println( result ); // java.awt.Point[x=100,y=200]
Ответ 11
Пожалуйста, обратитесь к следующему коду, который может вам помочь.
public static void main(String args[])
{
MethodClass obj = new MethodClass();
Method[] methods = obj.getClass().getMethods();
try
{
for(int i=0;i<methods.length;i++)
{
String name=methods[i].getName();
if(name.equals("A"))
{
methods[i].invoke(obj,"Test Parameters of A");
return;
}
}
}
catch(Exception ex)
{
System.out.println(ex.getMessage());
}
}
Спасибо....
Ответ 12
Method method = KeyWords.class.getMethod(Keyword);
String status = (String) method.invoke(method);
Ключевые слова - это имя класса, а KeyWord - переменная
Ответ 13
Я делаю так:
try {
YourClass yourClass = new YourClass();
Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class);
method.invoke(yourClass, parameter);
} catch (Exception e) {
e.printStackTrace();
}
Ответ 14
Student.java
class Student{
int rollno;
String name;
void m1(int x,int y){
System.out.println("add is" +(x+y));
}
private void m3(String name){
this.name=name;
System.out.println("danger yappa:"+name);
}
void m4(){
System.out.println("This is m4");
}
}
StudentTest.java
import java.lang.reflect.Method;
public class StudentTest{
public static void main(String[] args){
try{
Class cls=Student.class;
Student s=(Student)cls.newInstance();
String x="kichha";
Method mm3=cls.getDeclaredMethod("m3",String.class);
mm3.setAccessible(true);
mm3.invoke(s,x);
Method mm1=cls.getDeclaredMethod("m1",int.class,int.class);
mm1.invoke(s,10,20);
}
catch(Exception e){
e.printStackTrace();
}
}
}
Ответ 15
Вы должны использовать отражение - инициализировать объект класса, затем метод в этом классе, а затем вызвать этот метод для объекта с необязательными параметрами. Не забудьте обернуть следующий фрагмент в блок try-catch
Надеюсь, что это поможет!
Class<?> aClass = Class.forName(FULLY_QUALIFIED_CLASS_NAME);
Method method = aClass.getMethod(methodName, YOUR_PARAM_1.class, YOUR_PARAM_2.class);
method.invoke(OBJECT_TO_RUN_METHOD_ON, YOUR_PARAM_1, YOUR_PARAM_2);
Ответ 16
Это отлично работает для меня:
public class MethodInvokerClass {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, ClassNotFoundException, InvocationTargetException, InstantiationException {
Class c = Class.forName(MethodInvokerClass.class.getName());
Object o = c.newInstance();
Class[] paramTypes = new Class[1];
paramTypes[0]=String.class;
String methodName = "countWord";
Method m = c.getDeclaredMethod(methodName, paramTypes);
m.invoke(o, "testparam");
}
public void countWord(String input){
System.out.println("My input "+input);
}
}
Выход:
My input testparam
Я могу вызвать метод, передав его имя другому методу (например, main).
Ответ 17
с помощью import java.lang.reflect.*;
public static Object launchProcess(String className, String methodName, Class<?>[] argsTypes, Object[] methodArgs)
throws Exception {
Class<?> processClass = Class.forName(className); // convert string classname to class
Object process = processClass.newInstance(); // invoke empty constructor
Method aMethod = process.getClass().getMethod(methodName,argsTypes);
Object res = aMethod.invoke(process, methodArgs); // pass arg
return(res);
}
и вот как вы его используете:
String className = "com.example.helloworld";
String methodName = "print";
Class<?>[] argsTypes = {String.class, String.class};
Object[] methArgs = { "hello", "world" };
launchProcess(className, methodName, argsTypes, methArgs);
Ответ 18
для меня довольно простой и надежный способ - просто сделать метод вызывающего метода следующим образом:
public static object methodCaller(String methodName)
{
if(methodName.equals("getName"))
return className.getName();
}
тогда, когда вам нужно вызвать метод, просто поставьте что-то вроде этого
//calling a toString method is unnessary here, but i use it to have my programs to both rigid and self-explanitory
System.out.println(methodCaller(methodName).toString());