Como eu invoco um método Java quando é dado o nome do método como uma string?

Se eu tenho duas variables:

Object obj; String methodName = "getName"; 

Sem saber a class de obj , como posso chamar o método identificado por methodName ?

O método que está sendo chamado não tem parâmetros e um valor de retorno de String . É um getter para um bean Java .

Codificação do quadril, seria algo como:

 java.lang.reflect.Method method; try { method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..); } catch (SecurityException e) { ... } catch (NoSuchMethodException e) { ... } 

Os parâmetros identificam o método muito específico que você precisa (se houver vários sobrecarregados disponíveis, se o método não tiver argumentos, apenas forneça methodName ).

Então você invoca esse método chamando

 try { method.invoke(obj, arg1, arg2,...); } catch (IllegalArgumentException e) { ... } catch (IllegalAccessException e) { ... } catch (InvocationTargetException e) { ... } 

Novamente, deixe de fora os argumentos em .invoke , se você não tiver nenhum. Mas sim. Leia sobre o Java Reflection

Use a invocação de método da reflection:

 Class< ?> c = Class.forName("class name"); Method method = c.getDeclaredMethod("method name", parameterTypes); method.invoke(objectToInvokeOn, params); 

Onde:

  • "class name" é o nome da class
  • objectToInvokeOn é do tipo Object e é o object para o qual você deseja invocar o método
  • "method name" é o nome do método que você deseja chamar
  • parameterTypes é do tipo Class[] e declara os parâmetros que o método usa
  • params é do tipo Object[] e declara os parâmetros a serem passados ​​para o método

Para aqueles que querem um exemplo de código direto no Java 7:

Classe do 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."); } } 

Classe 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 } } 

Resultado: Mishka is 3 year(s) old.


Você pode invocar o construtor com parâmetros desta maneira:

 Constructor< ?> dogConstructor = dogClass.getConstructor(String.class, int.class); Object dog = dogConstructor.newInstance("Hachiko", 10); 

Alternativamente, você pode remover

 String dogClassName = "com.mypackage.bean.Dog"; Class< ?> dogClass = Class.forName(dogClassName); Object dog = dogClass.newInstance(); 

e fazer

 Dog dog = new Dog(); Method method = Dog.class.getMethod(methodName, ...); method.invoke(dog, ...); 

Sugestão de leitura: criando novas instâncias de class

O método pode ser chamado assim. Há também mais possibilidades (verifique a API de reflection), mas esta é a mais simples:

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

Primeiro não. Evite esse tipo de código. Ele tende a ser um código muito ruim e inseguro também (consulte a seção 6 das Diretrizes de Codificação Segura para a Linguagem de Programação Java, versão 2.0 ).

Se você precisar fazer isso, prefira java.beans à reflection. Feijão envolve reflection permitindo access relativamente seguro e convencional.

Para completar as respostas do meu colega, você pode querer prestar muita atenção em:

  • Chamadas estáticas ou de instâncias (em um caso, você não precisa de uma instância da class, no outro, pode ser necessário confiar em um construtor padrão existente que pode ou não estar lá)
  • chamada de método público ou não público (para este último, você precisa chamar setAccessible no método dentro de um bloco doPrivileged , outros findbugs não ficarão satisfeitos )
  • encapsulando em uma exceção de aplicativo mais gerenciável se você quiser jogar de volta as numerosas exceções do sistema java (daí a CCException no código abaixo)

Aqui está um antigo código java1.4 que leva em conta esses pontos:

 /** * Allow for instance call, avoiding certain class circular dependencies. 
* 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; }
 //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"); 
 Object obj; Method method = obj.getClass().getMethod("methodName", null); method.invoke(obj, null); 

Isso soa como algo que pode ser feito com o pacote Java Reflection.

http://java.sun.com/developer/technicalArticles/ALT/Reflection/index.html

Particularmente em Invoking Methods by Name:

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

Se você fizer a chamada várias vezes, poderá usar as novas alças de método introduzidas no Java 7. Aqui vamos nós para o seu método retornando uma String:

 Object obj = new Point( 100, 200 ); String methodName = "toString"; Class 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] 
 Method method = someVariable.class.getMethod(SomeClass); String status = (String) method.invoke(method); 

SomeClass é a class e someVariable é uma variável.

Por favor, consulte o código a seguir pode ajudá-lo.

 public static Method method[]; public static MethodClass obj; public static String testMethod="A"; public static void main(String args[]) { obj=new MethodClass(); method=obj.getClass().getMethods(); try { for(int i=0;i 

Obrigado....

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

Eu faço assim:

 try { YourClass yourClass = new YourClass(); Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class); method.invoke(yourClass, parameter); } catch (Exception e) { e.printStackTrace(); } 

Você deve usar reflection – init um object de class, em seguida, um método nessa class e, em seguida, invocar esse método em um object com parâmetros opcionais . Lembre-se de include o seguinte snippet no bloco try-catch

Espero que ajude!

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

Isso está funcionando bem para mim:

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

}

Saída:

My input testparam

Eu sou capaz de invocar o método passando seu nome para outro método (como main).

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

e aqui está como você usa:

 String className = "com.example.helloworld"; String methodName = "print"; Class< ?>[] argsTypes = {String.class, String.class}; Object[] methArgs = { "hello", "world" }; launchProcess(className, methodName, argsTypes, methArgs); 

para mim, uma maneira bastante simples e à prova de falhas seria simplesmente criar um método de método de chamada assim:

 public static object methodCaller(String methodName) { if(methodName.equals("getName")) return className.getName(); } 

então quando você precisa chamar o método simplesmente coloque algo como isto

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