How do I invoke a Java method when given the method name as a string?

JavaReflectionInvoke

Java Problem Overview


If I have two variables:

Object obj;
String methodName = "getName";

Without knowing the class of obj, how can I call the method identified by methodName on it?

The method being called has no parameters, and a String return value. It's a getter for a Java bean.

Java Solutions


Solution 1 - Java

Coding from the hip, it would be something like:

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

The parameters identify the very specific method you need (if there are several overloaded available, if the method has no arguments, only give methodName).

Then you invoke that method by calling

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

Again, leave out the arguments in .invoke, if you don't have any. But yeah. Read about Java Reflection

Solution 2 - Java

Use method invocation from reflection:

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

Where:

  • "class name" is the name of the class
  • objectToInvokeOn is of type Object and is the object you want to invoke the method on
  • "method name" is the name of the method you want to call
  • parameterTypes is of type Class[] and declares the parameters the method takes
  • params is of type Object[] and declares the parameters to be passed to the method

Solution 3 - Java

For those who want a straight-forward code example in Java 7:

Dog class:

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

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

Output: Mishka is 3 year(s) old.


You can invoke the constructor with parameters this way:

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

Alternatively, you can remove

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

and do

Dog dog = new Dog();

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

Suggested reading: Creating New Class Instances

Solution 4 - Java

The method can be invoked like this. There are also more possibilities (check the reflection api), but this is the simplest one:

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


}

Solution 5 - Java

First, don't. Avoid this sort of code. It tends to be really bad code and insecure too (see section 6 of Secure Coding Guidelines for the Java Programming Language, version 2.0).

If you must do it, prefer java.beans to reflection. Beans wraps reflection allowing relatively safe and conventional access.

Solution 6 - Java

To complete my colleague's answers, You might want to pay close attention to:

  • static or instance calls (in one case, you do not need an instance of the class, in the other, you might need to rely on an existing default constructor that may or may not be there)
  • public or non-public method call (for the latter,you need to call setAccessible on the method within an doPrivileged block, other findbugs won't be happy)
  • encapsulating into one more manageable applicative exception if you want to throw back the numerous java system exceptions (hence the CCException in the code below)

Here is an old java1.4 code which takes into account those points:

/**
 * 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;
}

Solution 7 - Java

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

Solution 8 - Java

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

Solution 9 - Java

Indexing (faster)

You can use FunctionalInterface to save methods in a container to index them. You can use array container to invoke them by numbers or hashmap to invoke them by strings. By this trick, you can index your methods to invoke them dynamically faster.

@FunctionalInterface
public interface Method {
    double execute(int number);
}

public class ShapeArea {
    private final static double PI = 3.14;

    private Method[] methods = {
        this::square,
        this::circle
    };

    private double square(int number) {
        return number * number;
    }

    private double circle(int number) {
        return PI * number * number;
    }

    public double run(int methodIndex, int number) {
        return methods[methodIndex].execute(number);
    }
}

Lambda syntax

You can also use lambda syntax:

public class ShapeArea {
    private final static double PI = 3.14;

    private Method[] methods = {
        number -> {
            return number * number;
        },
        number -> {
            return PI * number * number;
        },
    };

    public double run(int methodIndex, int number) {
        return methods[methodIndex].execute(number);
    }
}

Solution 10 - Java

If you do the call several times you can use the new method handles introduced in Java 7. Here we go for your method returning a 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]

Solution 11 - Java

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

Solution 12 - Java

This sounds like something that is doable with the Java Reflection package.

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

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

Solution 13 - Java

Here are the READY TO USE METHODS:

To invoke a method, without Arguments:

public static void callMethodByName(Object object, String methodName) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    object.getClass().getDeclaredMethod(methodName).invoke(object);
}

To invoke a method, with Arguments:

    public static void callMethodByName(Object object, String methodName, int i, String s) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        object.getClass().getDeclaredMethod(methodName, int.class, String.class).invoke(object, i, s);
    }

Use the above methods as below:

package practice;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

public class MethodInvoke {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {
        String methodName1 = "methodA";
        String methodName2 = "methodB";
        MethodInvoke object = new MethodInvoke();
        callMethodByName(object, methodName1);
        callMethodByName(object, methodName2, 1, "Test");
    }

    public static void callMethodByName(Object object, String methodName) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        object.getClass().getDeclaredMethod(methodName).invoke(object);
    }
    
    public static void callMethodByName(Object object, String methodName, int i, String s) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        object.getClass().getDeclaredMethod(methodName, int.class, String.class).invoke(object, i, s);
    }

    void methodA() {
        System.out.println("Method A");
    }
    
    void methodB(int i, String s) {
        System.out.println("Method B: "+"\n\tParam1 - "+i+"\n\tParam 2 - "+s);
    }
}

Output:

Method A
Method B:
Param1 - 1
Param 2 - Test

Solution 14 - Java

Please refer following code may help you.

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

Thanks....

Solution 15 - Java

Method method = someVariable.class.getMethod(SomeClass);
String status = (String) method.invoke(method);

SomeClass is the class and someVariable is a variable.

Solution 16 - Java

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

Solution 17 - Java

You should use reflection - init a class object, then a method in this class, and then invoke this method on an object with optional parameters. Remember to wrap the following snippet in try-catch block

Hope it helps!

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

Solution 18 - Java

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

and here is how you use it:

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

Solution 19 - Java

This is working fine for me :

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

}

Output:

My input testparam

I am able to invoke the method by passing its name to another method (like main).

Solution 20 - Java

With jooR it's merely:

on(obj).call(methodName /*params*/).get()

Here is a more elaborate example:

public class TestClass {

    public int add(int a, int b) { return a + b; }
    private int mul(int a, int b) { return a * b; }
    static int sub(int a, int b) { return a - b; }

}

import static org.joor.Reflect.*;

public class JoorTest {

    public static void main(String[] args) {
        int add = on(new TestClass()).call("add", 1, 2).get(); // public
        int mul = on(new TestClass()).call("mul", 3, 4).get(); // private
        int sub = on(TestClass.class).call("sub", 6, 5).get(); // static
        System.out.println(add + ", " + mul + ", " + sub);
    }
}

This prints:

>3, 12, 1

Solution 21 - Java

For those who are calling the method within the same class from a non-static method, see below codes:

class Person {
    public void method1() {
        try {
            Method m2 = this.getClass().getDeclaredMethod("method2");
            m1.invoke(this);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public void method2() {
        // Do something
    }

}

Solution 22 - Java

Suppose you're invoking a static method from a static method within the same class. To do that, you can sample the following code.

class MainClass
{
  public static int foo()
  {
    return 123;
  }

  public static void main(String[] args)
  {
    Method method = MainClass.class.getMethod("foo");
    int result = (int) method.invoke(null); // answer evaluates to 123
  }
}

To explain, since we're not looking to perform true object-oriented programming here, hence avoiding the creation of unnecessary objects, we will instead leverage the class property to invoke getMethod().

Then we will pass in null for the invoke() method because we have no object to perform this operation upon.

And finally, because we, the programmer, know that we are expecting an integer, then we explicitly cast the return value of the invoke() invocation to an integer.

Now you may wonder: "What even is the point of doing all this non-object oriented programming in Java?"

My use case was to solve Project Euler problems in Java. I have a single Java source file containing all the solutions, and I wanted to pass in command line arguments to determine which Project Euler problem to run.

Solution 23 - Java

for me a pretty simple and fool proof way would be to simply make a method caller method like so:

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

then when you need to call the method simply put something like this

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbrasskazooView Question on Stackoverflow
Solution 1 - JavaHenrik PaulView Answer on Stackoverflow
Solution 2 - JavaOwenView Answer on Stackoverflow
Solution 3 - JavasilverView Answer on Stackoverflow
Solution 4 - JavaPetr MacekView Answer on Stackoverflow
Solution 5 - JavaTom Hawtin - tacklineView Answer on Stackoverflow
Solution 6 - JavaVonCView Answer on Stackoverflow
Solution 7 - JavachickeninabiscuitView Answer on Stackoverflow
Solution 8 - JavaanujinView Answer on Stackoverflow
Solution 9 - JavaAmir FoView Answer on Stackoverflow
Solution 10 - JavaChristian UllenboomView Answer on Stackoverflow
Solution 11 - JavaMarcelView Answer on Stackoverflow
Solution 12 - JavazxcvView Answer on Stackoverflow
Solution 13 - JavaSandeep NallaView Answer on Stackoverflow
Solution 14 - JavaRahul KarankalView Answer on Stackoverflow
Solution 15 - JavaSubrahmanya PrasadView Answer on Stackoverflow
Solution 16 - Javauser8387971View Answer on Stackoverflow
Solution 17 - JavanurnachmanView Answer on Stackoverflow
Solution 18 - JavadinaView Answer on Stackoverflow
Solution 19 - JavaGautamView Answer on Stackoverflow
Solution 20 - JavaAndronicusView Answer on Stackoverflow
Solution 21 - JavachrizonlineView Answer on Stackoverflow
Solution 22 - JavaFriskySagaView Answer on Stackoverflow
Solution 23 - JavaSMayneView Answer on Stackoverflow