How can I invoke method from passing string? [duplicate] - java
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.
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
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
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
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);
}
}
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.
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;
}
Object obj;
Method method = obj.getClass().getMethod("methodName", null);
method.invoke(obj, null);
//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");
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);
}
}
Edit 2022
Just now I was thinking to provide you with a universal solution to work with all possible methods with variant number of arguments:
#FunctionalInterface
public interface Method {
Object execute(Object ...args);
}
public class Methods {
private Method[] methods = {
this::square,
this::rectangle
};
private double square(int number) {
return number * number;
}
private double rectangle(int width, int height) {
return width * height;
}
public Method run(int methodIndex) {
return methods[methodIndex];
}
}
Usage:
methods.run(1).execute(width, height);
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]
try {
YourClass yourClass = new YourClass();
Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class);
method.invoke(yourClass, parameter);
} catch (Exception e) {
e.printStackTrace();
}
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);
}
}
}
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
Method method = someVariable.class.getMethod(SomeClass);
String status = (String) method.invoke(method);
SomeClass is the class and someVariable is a variable.
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....
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();
}
}
}
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);
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);
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
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).
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
}
}
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.
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());
Related
Why can't I access a private method with the Java Reflection API?
I'm trying to access a private method, but it doesn't let me to, and throws the exception. How can I avoid the exception? I've tried a lot of other questions, but they all just point to using setAccessible(true), which I'm already using right now. import java.lang.reflect.*; class Reflection { public static void main (String[] args) { try { //Get class instance ReflectionExamples re = new ReflectionExamples(); Class<?> c = re.getClass(); System.out.println("Class name is " + c.getName()); //Get constructor of class Constructor<?> cons = c.getConstructor(); System.out.println("Constructor name is " + cons.getName()); System.out.println("List of methods are:"); //Iterate all methods Method[] methods = c.getMethods(); for (Method method : methods) { System.out.println(method.getName()); } //Desired method to call Method call = c.getDeclaredMethod("e"); //Unlock the private Method call.setAccessible(true); //Invoke the Method call.invoke(re); //Desired method to call Method call2 = c.getDeclaredMethod("a"); //Invoke the method call2.invoke(c); } catch(Throwable e) { System.err.println(e); } } } class ReflectionExamples { private String string = "String222222"; public int i = 0; public ReflectionExamples() { string = "String"; } private void e() { System.out.println("Char entered is not valid."); } public void f(char a) { System.out.println("awojiewfihuerhkuah"); } public void a() { System.out.println(string); } } And I get: java.security.AccessControlException: access denied ("java.lang.reflect.ReflectPermission" "suppressAccessChecks")
How to give parameters to hashmap getMethod
I have this code: public static Map< String, Method > supplierFunctionMap = new HashMap< String, Method >(); static { try { supplierFunctionMap.put( "11111-200", SupplierConfiguration.class.getMethod("supplier_X")); supplierFunctionMap.put( "11111-210", SupplierConfiguration.class.getMethod("supplier_X")); } catch (NoSuchMethodException e) { e.printStackTrace(); } } public static void supplierHasConfig(String supplierNumber) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { supplierFunctionMap.get(supplierNumber).invoke(null); } public static void supplier_X() throws NotesException{ Now what I want to do is the following. I want to add an extra parameter to supplier_X. So for example supplier_X(int supplierNumber). Now in the code above I call the method via a HashMap. How do I add these parameters into the hashmap?
Change signature of method to declare desired arguments public static void supplier_X(Object arg1, Object arg2) throws NotesException { Invoke your Method passing desired values ... supplierFunctionMap.get(supplierNumber).invoke(null, new Object(), new Object()); ... replace new Object() with actual type and values you want to pass. Method.invoke() takes an object on which you want to execute the method as first parameter (in your case you are passing a null since method is static) and list of arguments to pass in method. Hope it helps! Edit: if you want to tied up parameters create wrapper class to store parameters and Method together class MethodWithParameters { private Method method; private final List<Object> parameters = new ArrayList<>(); // get, set } And use such class as a value of your Map Map<String, MethodWithParameters> supplierFunctionMap = new HashMap<>();
This will helps you: import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; public class Test { public static void main(String[] args) { supplierHasConfig("11111-210"); } public static Map<String, Method> supplierFunctionMap = new HashMap<String, Method>(); static { try { supplierFunctionMap.put("11111-200", Test.class.getMethod("supplier_X", String.class)); supplierFunctionMap.put("11111-210", Test.class.getMethod("supplier_X", String.class)); } catch (NoSuchMethodException e) { e.printStackTrace(); } } public static void supplierHasConfig(String supplierNumber) { Object[] obj = {"Hi"}; try { supplierFunctionMap.get(supplierNumber).invoke(Test.class.newInstance(), obj); } catch (IllegalAccessException | InvocationTargetException |InstantiationException e) { e.printStackTrace(); } } public static void supplier_X(String param) { System.out.println(param); } }
Java invoke method using reflection
I am trying to invoke a method using reflection. The method I am invoking is not static and in the same class I am invoking it from. A simplified version of my code: public class Test { public static void main(String[] args) { Test instance = new Test(); if (args.length > 0) { instance.doWork(args[0]); } } private void doWork(String methodName) { Method method; try { method = this.getClass().getMethod(methodName); method.invoke(this); } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { [...] } } private void MethodOne() { ... }; private void MethodTwo() { ... }; [...] private void MethodTwenty() { ... }; } What I am getting is a java.lang.NoSuchMethodException: correct.package.and.class.MethodTwo() despite the package / class / method existing. Can someone tell me what I am doing wrong?
What I am getting is a java.lang.NoSuchMethodException: correct.package.and.class.MethodTwo()... you are calling the getMethod() which is not giving back the private method Assuming that arg[0] has the right name of the method (if not you'll get a java.lang.NoSuchMethodException again), 2 thing must be done here: you need to use getDeclaredMethod (because MethodOne is private declared) your need to set the flag for access to it .setAccessible(true) (this will allow you to invoke a method that is declared private) Example: Method method; try { method = f.getClass().getDeclaredMethod("doThis"); method.setAccessible(true); method.invoke(f); } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { System.err.println("Opala, somethign went wrong here!"); }
The way you are accessing method is correct. The method access specifier is private. Thus it is throwing error. Please change the access specifier to public, it will work. import java.lang.reflect.Method; public class Test { public static void main(String[] args) { Test instance = new Test(); if (args.length > 0) { instance.doWork(args[0]); } } private void doWork(String methodName) { Method method; try { method = this.getClass().getMethod(methodName); method.invoke(this); } catch (Exception e) { } } public void MethodOne() { System.out.println("Method 1"); }; public void MethodTwo() { System.out.println("Method 2"); }; public void MethodTwenty() { System.out.println("Method 3"); }; } If you are trying to access private methods or constructors, you need to change the code. Thanks, Thiruppathi S
CLASS TO INVOKE METHODS FROM public class Computer { private String brandName; private int yearManufactured; public String getBrandName() { return brandName; } public void setBrandName(String brandName) { this.brandName = brandName; } public int getYearManufactured() { return yearManufactured; } public void setYearManufactured(int yearManufactured) { this.yearManufactured = yearManufactured; } } IMPLEMENTATION CLASS public class Test { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException{ Class curClass = Computer.class; Method[] allMethods = curClass.getDeclaredMethods(); Computer myComputer = new Computer(); for(int c = 0; c < allMethods.length; c++){ Class[] parameterTypes = allMethods[c].getParameterTypes(); for(Class parameterType: parameterTypes){ System.out.println(parameterType.getName()); switch(parameterType.getName()){ case "java.lang.String": allMethods[c].invoke(myComputer, "LENOVO"); break; case "int": allMethods[c].invoke(myComputer, 2021); break; } } } System.out.println("BRAND NAME :"+myComputer.getBrandName()); System.out.println("YEAR MANUFACTURED: "+myComputer.getYearManufactured()); } }
Dynamically invoke a method from a varying class
I have a requirement where in i need to invoke method from class in a particular pattern which is obtained as input argument. public RandomMethod(String ClassName){ //Eg For Class Name Abc , there is a method AbcProcessor which i need to invoke ClassName.ClassNameProcessor } Since i am getting the argument as String , i am not able to figure out how to cast String into a form where i can call something like Abc.AbcProcessor() I believe there is some way to do this using reflections. But i am not sure how to proceed.
By reflection you can do that, try following sample: Class A: public class A { public void print(){ System.out.println("A"); } } Class B: public class B { public void print(){ System.out.println("B"); } } Invoking print() from A and B: public class Test { public static void callPrint(String className){ try { Class clazz = Class.forName(className); Object obj = clazz.newInstance(); clazz.getDeclaredMethod("print").invoke(obj); } catch (Exception ex) { ex.printStackTrace(); } } public static void main(String[] args) { callPrint("test.A"); callPrint("test.B"); } }
You need to use reflecton, indeed: public void randomMethod(String fullyQualifiedClassName, String methodName) throws ReflectiveOperationException { Class<?> clazz = Class.forName(fullyQualifiedClassName); clazz.getMethod(methodName).invoke(null); } which would work assuming you are calling public static method with no arguments
How do I invoke a Java method when given the method name as a string?
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.
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
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
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
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); } }
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.
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; }
Object obj; Method method = obj.getClass().getMethod("methodName", null); method.invoke(obj, null);
//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");
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); } } Edit 2022 Just now I was thinking to provide you with a universal solution to work with all possible methods with variant number of arguments: #FunctionalInterface public interface Method { Object execute(Object ...args); } public class Methods { private Method[] methods = { this::square, this::rectangle }; private double square(int number) { return number * number; } private double rectangle(int width, int height) { return width * height; } public Method run(int methodIndex) { return methods[methodIndex]; } } Usage: methods.run(1).execute(width, height);
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]
try { YourClass yourClass = new YourClass(); Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class); method.invoke(yourClass, parameter); } catch (Exception e) { e.printStackTrace(); }
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); } } }
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
Method method = someVariable.class.getMethod(SomeClass); String status = (String) method.invoke(method); SomeClass is the class and someVariable is a variable.
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....
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(); } } }
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);
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);
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
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).
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 } }
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.
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());