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

Se eu tiver duas variáveis:

Object obj;
String methodName = "getName";

sem conhecer a classe de obj, Como posso chamar o método identificado por methodName nele?

o método a ser chamado não tem parâmetros, e um valor de retorno String. É um getter para um feijão Java.

Author: Joachim Sauer, 2008-10-02

18 answers

Codificação da anca, seria algo do género:
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 de que necessita (se existirem várias sobrecarregadas disponíveis, se o método não tiver argumentos, dê apenas methodName).

Então 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 tem nenhum. Mas sim. Leia sobre reflexão Java

 849
Author: Henrik Paul, 2016-09-29 14:13:34

Utilizar método invocação {[11] } da reflexão:

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

Em que:

  • "class name" é o nome da classe
  • objectToInvokeOn é do tipo objecto e é o objecto que deseja invocar o método em
  • "method name" é o nome do método que você quer chamar
  • parameterTypes é do tipo Class[] e declara os parâmetros que o método toma
  • params é do tipo Object[] e declara que os parâmetros devem ser passados ao método
 161
Author: Owen, 2018-04-20 17:42:48

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

Dog classe:

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 classe:

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.


Pode invocar o construtor com os parâmetros desta forma:

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

Em alternativa, 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, ...);

Leitura sugerida: criar novas instâncias de classe

 67
Author: silver, 2015-10-31 07:06:05
O método pode ser invocado assim. Existem também mais possibilidades (verifique a api de reflexão), 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);
    }



}
 51
Author: Petr Macek, 2008-10-02 05:33:31
Primeiro, evitem este tipo de código. Tende a ser muito mau código e inseguro também (ver secção 6 de Secure Coding Guidelines para o Java Programming Language, version 2.0 ).

Se tens de o fazer, prefere java.feijões para reflexão. Beans Wraps reflexão que permite um acesso relativamente seguro e convencional.

 16
Author: Tom Hawtin - tackline, 2015-02-13 19:26:23
Para completar as respostas do meu colega, talvez queira prestar muita atenção a:
  • estática ou chamadas de instância (num caso, você não precisa de uma instância da classe, no outro, você pode precisar 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 setacessible sobre o método dentro de um bloco doPrivileged , outros não serão feliz.)
  • encapsulando-se em mais uma excepção aplicativa gerenciável se você quiser descartar as inúmeras exceções do sistema java (daí a Ccexcepção no código abaixo)

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

/**
 * 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;
}
 12
Author: VonC, 2008-10-02 05:51:12
//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");
 10
Author: anujin, 2013-04-30 05:46:18
Object obj;

Method method = obj.getClass().getMethod("methodName", null);

method.invoke(obj, null);
 8
Author: chickeninabiscuit, 2008-10-02 05:22:24

Isto parece algo que é possível fazer com o pacote de reflexão Java.

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

Em especial em invocar os métodos pelo nome:

Importar java.idioma.reflectir.*;

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);
     }
  }
}
 6
Author: zxcv, 2008-10-02 05:22:24

Se fizer a chamada várias vezes pode usar os novos métodos introduzidos 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<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]
 6
Author: Christian Ullenboom, 2017-02-28 22:02:59
Method method = someVariable.class.getMethod(SomeClass);
String status = (String) method.invoke(method);

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

 4
Author: Subrahmanya Prasad, 2018-04-20 17:44:05

Por favor consulte o seguinte código que o poderá ajudar.

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<method.length;i++)
        {
            String name=method[i].getName();
            if(name==testMethod)
            {   
                method[i].invoke(name,"Test Parameters of A");
            }
        }
    }
    catch(Exception ex)
    {
        System.out.println(ex.getMessage());
    }
}
Obrigado....
 4
Author: Rahul Karankal, 2018-04-24 12:37:58
Estudante.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();
        }
     }
}
 3
Author: user8387971, 2018-04-20 17:43:08

Eu faço isto assim:

try {
    YourClass yourClass = new YourClass();
    Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class);
    method.invoke(yourClass, parameter);
} catch (Exception e) {
    e.printStackTrace();
}
 3
Author: Marcel Jacques Machado, 2018-04-20 17:44:22

Você deve usar a reflexão-init um objecto de classe, depois um método nesta classe, e depois invocar este método num objecto com parâmetros opcionais. Lembre-se de embrulhar o seguinte excerto em Tente-catch Bloco

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);
 1
Author: nurxyz, 2015-07-09 14:51:37
Isto está a funcionar 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);
}

}

Resultado:

My input testparam

Sou capaz de invocar o método passando o seu nome para outro método (como o principal).

 1
Author: Laxman G, 2016-08-10 13:40:15

Utilizar 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ê o usa:

String className = "com.example.helloworld";
String methodName = "print";
Class<?>[] argsTypes = {String.class,  String.class};
Object[] methArgs = { "hello", "world" };   
launchProcess(className, methodName, argsTypes, methArgs);
 1
Author: dina, 2016-11-23 07:32:23
Para mim, uma maneira simples e tola de provar seria simplesmente fazer um método de chamada de método como este.
public static object methodCaller(String methodName)
{
    if(methodName.equals("getName"))
        return className.getName();
}

Então quando você precisa chamar o método simplesmente colocar algo assim

//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()); 
 -9
Author: SMayne, 2014-04-18 15:11:11