Related
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());
I'm testing with Java reflection and trying to apply overloaded method to parameters according to their type..
However, I have NoSuchMethodException even though the method I tried to get is public. This exception still appears when I used getDeclaredMethod.
Here's the main program
public class Test {
public static void main(Object... inputs){
InputManipulation test = new InputManipulation();
for (Object input: inputs){
Class ownerClass = test.getClass();
Class inputClass = input.getClass();
Method method = ownerClass.getDeclaredMethod("add", inputClass);
method.invoke(test, "Testing reflection");
}
}
}
And here's the self-defined InputManipulation class
public class InputManipulation {
Integer total;
public InputManipulation(){this.total = 0;}
public void add(Integer num){this.total += num;}
public void add(String str){System.out.println(str);}
}
Thanks in advance!
I now changed the Test class as follows.. but the problem still exists.
public class Test {
public static void main(String[] args){
Test testExample = new Test();
testExample.testMethod("String1", 1, "String2");
}
public void testMethod(Object... inputs){
InputManipulation test = new InputManipulation();
for (Object input: inputs){
Class ownerClass = test.getClass();
Class inputClass = input.getClass();
Method method = ownerClass.getDeclaredMethod("add", inputClass);
method.invoke(test, "Testing reflection");
}
}
}
I also tried putting the inputClass into an array of Class, as suggested by another post, but it didn't help..
There seems to be a few issues with the initial code you provided and as others have suggested using an IDE would have pointed some of the issues out pretty quickly. However, I have taken your update and fixed the code to call the proper method in the loop you provided of input types.
First change your InputManipulation class like so:
public class InputManipulation {
Integer total;
public InputManipulation() {
this.total = 0;
}
public void add(Integer num) {
this.total += num;
System.out.println(this.total);
}
public void add(String str) {
System.out.println(str);
}
}
Now alter your Test class like so:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
Test testExample = new Test();
testExample.testMethod("String1", 1, "String2");
}
public void testMethod(Object... inputs){
InputManipulation test = new InputManipulation();
for (Object input: inputs){
Class<? extends Object> ownerClass = test.getClass();
Class<? extends Object> inputClass = input.getClass();
//Method method; //not needed
try {
ownerClass.getDeclaredMethod("add", inputClass).invoke(test, input);
} catch (NoSuchMethodException | SecurityException |
IllegalAccessException | IllegalArgumentException |
InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
I used these readings to help guide my answer, but altered the way I invoked the method:
http://tutorials.jenkov.com/java-reflection/methods.html
public class Test {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
Test testExample = new Test();
testExample.testMethod("String1", 1, "String2");
}
public void testMethod(Object... inputs) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
InputManipulation test = new InputManipulation();
for (Object input: inputs){
Class ownerClass = test.getClass();
Class inputClass = input.getClass();
Method method = ownerClass.getDeclaredMethod("add", inputClass);
method.invoke(test, input);
}
}
}
Your problem was caused by this method.invoke(test, "Testing reflection");
You iterate through 2 types of arguments and depends of this argument you invoke method 'add'. When you tried to invoke method with argument Integer you pass to method String parameter that causes error
I am trying to run a class from another class. But it asks me to change the type when I store the class name in an array. I want the user to enter a number which would be fed into the array and run the class at that array value.
Here is my code so far:
public class All_Challenges {
public static void main(String[] args) {
System.out.println("Which class do you want to run?: ");
System.out.println("1. The first class");
Class[] theFiles = new Class[31];
theFiles[1] = Challenge_1_Whats_Your_Name.main(args);
theFiles[1].main(args);
}
}
The last two lines are giving me an error because they are making me change the class type from The void to type class and then making add a return statement. I have around 30 of these so I would prefer not to have to change my main method in all my other classes. What stuff should I write so that I don't have to do this. I think it's something to do with what "type" my array is. Or maybe it's to do with the line main.(args);
Weird part is that it doesn't ask me to change the type when I don't call it from an array.
The problem is that you are trying to put a method to array of classes.
Class[] theFiles = new Class[31];
theFiles[1] = Challenge_1_Whats_Your_Name.class;
try {
theFiles[1].getMethod("main", String[].class).invoke(args);
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
That should work for you
You can do it using reflections:
public class TestMain {
private static final Class<?>[] classArray = {A.class, B.class};
public static void main(String[] args) {
for (Class<?> classExec : classArray) {
try {
//get main
Method method = classExec.getMethod("main", String[].class);
method.invoke(null, (Object) args);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
public static class A {
public static void main(String[] args) {
System.out.println("A");
}
}
public static class B {
public static void main(String[] args) {
System.out.println("B");
}
}
}
Reference: https://stackoverflow.com/a/4980149/1255493
I want to route certain chars to methods, so that when the char is typed in the command-line the method is then executed.
Based on the answer How to call a method stored in a HashMap, I'm mapping these chars to methods by using the "Command" design-pattern.
However I want to generically implement this, so it seems that I need to implement reflection in order to use the Method class as a parameter. My attempt is getting a NullPointerException on the field private Method method in my anonymous class...
Here is my code:
import java.lang.reflect.Method;
public interface InvokesMethod {
public void invokeMethod() throws Exception;
public void setMethod(Method method);
} // end of interface
import java.util.HashMap;
import java.lang.reflect.Method;
public class Terminal {
public HashMap<Character, InvokesMethod> commands;
public Terminal() {
this.commands = new HashMap<Character, InvokesMethod>();
try {
this.setCommand('p',
this.getClass().getDeclaredMethod("printHelloWorld"));
} catch (Exception e) {
e.printStackTrace();
}
}
private void printHelloWorld() {
System.out.println("Hello World!");
}
private void setCommand(char letter, Method method) {
this.commands.put(letter, new InvokesMethod() {
// NullPointerException starts here in the stack-trace:
private Method method;
#Override
public void invokeMethod() throws Exception {
method.invoke(null);
}
#Override
public void setMethod(Method method) {
this.method = method;
}
}).setMethod(method);
}
public void executeCommand(char letter) throws Exception {
this.commands.get(letter).invokeMethod();
}
} // end of class
public class Main() {
public static void main(String[] args) {
Terminal commandLine = new Terminal();
try {
commandLine.executeCommand('p');
} catch (Exception e) {
e.printStackTrace();
}
}
} // end of class
Regards to your code you didn't initiate method. Bear in mind that execute with null you must call public static method:
Your other issue , you didn't initiated interface properly. Here is working example:
InvokesMethodItf
public interface InvokesMethodItf {
public void invokeMethod() throws Exception;
public void setMethod(Method method);
}
InvokesMethod
public class InvokesMethod implements InvokesMethodItf{
private Method method;
#Override
public void invokeMethod() throws Exception {
method.invoke(null);
}
#Override
public void setMethod(Method method) {
this.method = method;
}
}
Terminal
public class Terminal {
public HashMap<Character, InvokesMethodItf> commands;
public Terminal() {
this.commands = new HashMap<Character, InvokesMethodItf>();
try {
this.setCommand('p',
this.getClass().getDeclaredMethod("printHelloWorld"));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void printHelloWorld() {// method.invoke(null) looking for "static" method
System.out.println("Hello World!");
}
private void setCommand(char letter, Method method) {
InvokesMethodItf inv = new InvokesMethod();
inv.setMethod(method);
this.commands.put(letter, inv);
}
public void executeCommand(char letter) throws Exception {
this.commands.get(letter).invokeMethod();
}
}
Main
public class Main {
public static void main(String[] args) {
Terminal commandLine = new Terminal();
try {
commandLine.executeCommand('p');
} catch (Exception e) {
e.printStackTrace();
}
}
}
Output:
Hello World!
Thanks to #Maxim's original suggestion here, I have an alternate solution by setting the methods as Strings in the HashMap instead --
import java.util.HashMap;
import java.lang.reflect.Method;
public class Terminal {
private HashMap<Character, String> commands;
public Terminal() {
this.commands = new HashMap<Character, String>();
this.commands.put('p', "printHelloWorld");
}
private void printHelloWorld() {
System.out.println("Hello World!");
}
public void executeCommand(char letter) throws Exception {
Method method = getClass().getDeclaredMethod(this.commands.get(letter));
method.invoke(this);
}
public class Main {
public static void main(String[] args) {
Terminal commandLine = new Terminal();
try {
commandLine.executeCommand('p');
} catch (Exception e) {
e.printStackTrace();
}
}
} // end of class
Output:
Hello World!
Now to figure out how to pass parameters to the reflected methods...
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());