JAVA: Calling Unknown Object Class Method and Passing it's Parameters - java

The objective is simple, I want to create a method which load a class dynamically, access its method and passing their parameters value and getting the return value at run-time.
Class which will be called
class MyClass {
public String sayHello() {
return "Hello";
}
public String sayGoodbye() {
return "Goodbye";
}
public String saySomething(String word){
return word;
}
}
Main Class
public class Main {
public void loadClass() {
try {
Class myclass = Class.forName(getClassName());
//Use reflection to list methods and invoke them
Method[] methods = myclass.getMethods();
Object object = myclass.newInstance();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().startsWith("saySome")) {
String word = "hello world";
//**TODO CALL OBJECT METHOD AND PASS ITS PARAMETER**
} else if (methods[i].getName().startsWith("say")) {
//call method
System.out.println(methods[i].invoke(object));
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private String getClassName() {
//Do appropriate stuff here to find out the classname
return "com.main.MyClass";
}
public static void main(String[] args) throws Exception {
new Main().loadClass();
}
}
My question is how to invoke method with parameters and passing its value? also getting the return value and its type.

I think you're just missing the fact that you can pass in arguments to invoke, as an Object[]:
Object result = methods[i].invoke(object, new Object[] { word });
Or using varargs, if you prefer:
Object result = methods[i].invoke(object, word);
(The above two calls are equivalent.)
See the documentation for Method.invoke for more details.

simply create the object of MyClass invoke the function like this
MyClass mc = new MyClass();
String word = "hello world";
String returnValue = mc.saySomething(word);
System.out.println(returnValue);//return hello world here
or do this
Class myclass = Class.forName(getClassName());
Method mth = myclass.getDeclaredMethod(methodName, params);
Object obj = myclass.newInstance();
String result = (String)mth.invoke(obj, args);

Try ::
Class c = Class.forName(className);
Method m = c.getDeclaredMethod(methodName, params);
Object i = c.newInstance();
String result = (String)m.invoke(i, args);

Related

Get Method reference from Method object

I have a method that expects a method reference:
expectsMethodRef(obj::someMethod);
I now only retrieve the method at compiletime with reflection. How do I get the method reference from a Method object?
Method method = obj.class.getMethod(methodNameStr);
expectsMethodRef(<how to input my method here?>);
You just need to use Method.invoke. Here is an example:
public class SomeObject{
public String someMethod(){
return "Test";
}
}
public String expectsMethodRef( Function<SomeObject, String> f ){
SomeObject so = new SomeObject();
return f.apply(so);
}
And here is how you invoke using plain lambda and Method object.
//plain lmbda
expectsMethodRef( SomeObject::someMethod );
//with method object
Method someMethod = SomeObject.class.getMethod("someMethod");
expectsMethodRef( (so) -> {
try {
return (String)someMethod.invoke(so);
} catch (Exception e) {
return null;
}
} );

How to access getter method of bean class using reflection api?

Why the value is null for the variable2 , if I instantiate the class using Reflection API?
Where, the value of Variable1 is returned correctly as per the set and here I instantiated the object normally.
How can I obtain the value of variable2 using ReflectionAPI?
package com.OP.app;
public class Bean {
private String variable1;
private String variable2;
public String getVariable1() {
return variable1;
}
public void setVariable1(String variable1) {
this.variable1 = variable1;
}
public String getVariable2() {
return variable2;
}
public void setVariable2(String variable2) {
this.variable2 = variable2;
}
}
package com.OP.app;
import java.lang.reflect.Method;
public class ObjectCall {
public static void main(String []args){
Bean beanobject = new Bean();
beanobject.setVariable1("Ram");
beanobject.setVariable2("Rakesh");
System.out.println(beanobject.getVariable1());
String path = "com.OP.app.Bean";
Class<?> newClass;
try {
newClass = Class.forName(path);
Object obj = newClass.newInstance();
String getMethod = "getVariable2";
Method getNameMethod = obj.getClass().getMethod(getMethod);
String name = (String) getNameMethod.invoke(obj);
System.out.println(name);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // convert string classname to class
}
}
Output :
Ram
null
That is beause you are invoking the method on newly created object (e.g. obj) which does not have values set for variable1 and variable2, e.g.:
Object obj = newClass.newInstance();
The above will create a new Object of Bean class with null values for variable1 and variable2. If you want to print the values set in beanobject method then you need to invoke the getter method with beanobject. i.e. change
String name = (String) getNameMethod.invoke(obj);
to
String name = (String) getNameMethod.invoke(beanobject);
You create a new instance of the target class where no values set.
Object obj = newClass.newInstance();
Method getNameMethod = obj.getClass().getMethod(getMethod);
Change this line and it should work:
Method getNameMethod = beanobject.getClass().getMethod(getMethod);
Additional:
Your naming of variables isn't very good. I would refactoring the code to this for better reading:
public static void main(String[] args) {
Bean beanInstance = new Bean();
beanInstance.setVariable1("Ram");
beanInstance.setVariable2("Rakesh");
System.out.println("Value 1 of fresh bean instance: " + beanInstance.getVariable1());
String beanType = Bean.class.getName();
Class<?> beanClazz;
try {
beanClazz = Class.forName(beanType);
String getterMethodName = "getVariable2";
Method getterMethod = beanClazz.getMethod(getterMethodName);
Object returnValue = getterMethod.invoke(beanInstance);
System.out.println("Value 2 of by reflection loaded bean instance: " + String.valueOf(returnValue));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // convert string classname to class
}

In Java, invoke method using reflection and without giving invoker object type and multiple parameters type? [duplicate]

Consider the following snippet:
public class ReflectionTest {
public static void main(String[] args) {
ReflectionTest test = new ReflectionTest();
String object = new String("Hello!");
// 1. String is accepted as an Object
test.print(object);
// 2. The appropriate method is not found with String.class
try {
java.lang.reflect.Method print
= test.getClass().getMethod("print", object.getClass());
print.invoke(test, object);
} catch (Exception ex) {
ex.printStackTrace(); // NoSuchMethodException!
}
}
public void print(Object object) {
System.out.println(object.toString());
}
}
getMethod() is obviously unaware that a String could be fed to a method that expects an Object (indeed, it's documentation says that it looks for method with the specified name and exactly the same formal parameter types).
Is there a straightforward way to find methods reflectively, like getMethod() does, but taking polymorphism into account, so that the above reflection example could find the print(Object) method when queried with ("print", String.class) parameters?
The reflection tutorial
suggest the use of Class.isAssignableFrom() sample for finding print(String)
Method[] allMethods = c.getDeclaredMethods();
for (Method m : allMethods) {
String mname = m.getName();
if (!mname.startsWith("print") {
continue;
}
Type[] pType = m.getGenericParameterTypes();
if ((pType.length != 1)
|| !String.class.isAssignableFrom(pType[0].getClass())) {
continue;
}
}
The easy way to do this is via java.beans.Statement or java.beans.Expression. Does all these hard yards for you.
getMethod() is obviously unaware that
a String could be fed to a method
that expects an Object
'Unaware' is a strange way to put it. getMethod() adheres to its specification. You have to supply the formal parameters, not the types of the actual arguments.
FYI, it is how I invoke method using reflection with multiple parameters without giving their types.
public class MyMethodUtils {
/**
* Need to pass parameter classes
*/
public static Object invoke(Object invoker, String methodName, Object[] parameters, Class[] parameterClasses) throws Exception {
Method method = invoker.getClass().getMethod(methodName, parameterClasses);
Object returnValue = method.invoke(invoker, parameters);
return returnValue;
}
/**
* No need to pass parameter classes
*/
public static Object invoke(Object invoker, String methodName, Object[] parameters) throws Exception {
Method[] allMethods = invoker.getClass().getDeclaredMethods();
Object returnValue = null;
boolean isFound = false;
for (Method m : allMethods) {
String mname = m.getName();
if (!mname.equals(methodName)) {
continue;
}
Class[] methodParaClasses = m.getParameterTypes();
for (int i = 0; i < methodParaClasses.length; i++) {
Class<?> parameterClass = parameters[i].getClass();
Class<?> methodParaClass = methodParaClasses[i];
boolean isAssignable = methodParaClass.isAssignableFrom(parameterClass);
if (!isAssignable) {
continue;
}
}
returnValue = m.invoke(invoker, parameters);
isFound = true;
}
if (!isFound) {
throw new RuntimeException("Cannot find such method");
}
return returnValue;
}
}
Sample Usage:
MyMethodUtils.invoke(student, "setNameAndMarks", new Object[] { "John", marks }, new Class[] { String.class, Collection.class });
MyMethodUtils.invoke(student, "setNameAndMarks", new Object[] { "John", marks });
However, for the method invoke(Object invoker, String methodName, Object[] parameters), it is possible to invoke wrong method if the signature is ambiguous. For example, if there is two methods for the invoker:
public void setNameAndMarks(String name, Collection<Integer> marks);
public void setNameAndMarks(String name, ArrayList<Integer> marks);
Passing the following parameter may invoke wrong method
setNameAndMarks("John", new ArrayList<Integer>());

How do I pass a class as a parameter in Java?

Is there any way to pass class as a parameter in Java and fire some methods from that class?
void main()
{
callClass(that.class)
}
void callClass(???? classObject)
{
classObject.somefunction
// or
new classObject()
//something like that ?
}
I am using Google Web Toolkit and it does not support reflection.
public void foo(Class c){
try {
Object ob = c.newInstance();
} catch (InstantiationException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
}
}
Here are some good examples on Reflection API
How to invoke method using reflection
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);
}
}
}
Also See
Java Reflection
public void callingMethod(Class neededClass) {
//Cast the class to the class you need
//and call your method in the class
((ClassBeingCalled)neededClass).methodOfClass();
}
To call the method, you call it this way:
callingMethod(ClassBeingCalled.class);
Construct your method to accept it-
public <T> void printClassNameAndCreateList(Class<T> className){
//example access 1
System.out.print(className.getName());
//example access 2
ArrayList<T> list = new ArrayList<T>();
//note that if you create a list this way, you will have to cast input
list.add((T)nameOfObject);
}
Call the method-
printClassNameAndCreateList(SomeClass.class);
You can also restrict the type of class, for example, this is one of the methods from a library I made-
protected Class postExceptionActivityIn;
protected <T extends PostExceptionActivity> void setPostExceptionActivityIn(Class <T> postExceptionActivityIn) {
this.postExceptionActivityIn = postExceptionActivityIn;
}
For more information, search Reflection and Generics.
Use
void callClass(Class classObject)
{
//do something with class
}
A Class is also a Java object, so you can refer to it by using its type.
Read more about it from official documentation.
This kind of thing is not easy. Here is a method that calls a static method:
public static Object callStaticMethod(
// class that contains the static method
final Class<?> clazz,
// method name
final String methodName,
// optional method parameters
final Object... parameters) throws Exception{
for(final Method method : clazz.getMethods()){
if(method.getName().equals(methodName)){
final Class<?>[] paramTypes = method.getParameterTypes();
if(parameters.length != paramTypes.length){
continue;
}
boolean compatible = true;
for(int i = 0; i < paramTypes.length; i++){
final Class<?> paramType = paramTypes[i];
final Object param = parameters[i];
if(param != null && !paramType.isInstance(param)){
compatible = false;
break;
}
}
if(compatible){
return method.invoke(/* static invocation */null,
parameters);
}
}
}
throw new NoSuchMethodException(methodName);
}
Update:
Wait, I just saw the gwt tag on the question. You can't use reflection in GWT
Adding <T> T as return type worked for me. Ex with json deserialize
public static <T> T fromJson(String json, Class<T> classOfT){
return gson().fromJson(json, classOfT);
}
I am not sure what you are trying to accomplish, but you may want to consider that passing a class may not be what you really need to be doing. In many cases, dealing with Class like this is easily encapsulated within a factory pattern of some type and the use of that is done through an interface. here's one of dozens of articles on that pattern: http://today.java.net/pub/a/today/2005/03/09/factory.html
using a class within a factory can be accomplished in a variety of ways, most notably by having a config file that contains the name of the class that implements the required interface. Then the factory can find that class from within the class path and construct it as an object of the specified interface.
As you said GWT does not support reflection. You should use deferred binding instead of reflection, or third party library such as gwt-ent for reflection suppport at gwt layer.
Se these:
http://download.oracle.com/javase/tutorial/extra/generics/methods.html
here is the explaniation for the template methods.
Have a look at the reflection tutorial and reflection API of Java:
https://community.oracle.com/docs/DOC-983192enter link description here
and
http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html
Class as paramater. Example.
Three classes:
class TestCar {
private int UnlockCode = 111;
protected boolean hasAirCondition = true;
String brand = "Ford";
public String licensePlate = "Arizona 111";
}
--
class Terminal {
public void hackCar(TestCar car) {
System.out.println(car.hasAirCondition);
System.out.println(car.licensePlate);
System.out.println(car.brand);
}
}
--
class Story {
public static void main(String args[]) {
TestCar testCar = new TestCar();
Terminal terminal = new Terminal();
terminal.hackCar(testCar);
}
}
In class Terminal method hackCar() take class TestCar as parameter.

Using java.lang.reflect.getMethod with polymorphic methods

Consider the following snippet:
public class ReflectionTest {
public static void main(String[] args) {
ReflectionTest test = new ReflectionTest();
String object = new String("Hello!");
// 1. String is accepted as an Object
test.print(object);
// 2. The appropriate method is not found with String.class
try {
java.lang.reflect.Method print
= test.getClass().getMethod("print", object.getClass());
print.invoke(test, object);
} catch (Exception ex) {
ex.printStackTrace(); // NoSuchMethodException!
}
}
public void print(Object object) {
System.out.println(object.toString());
}
}
getMethod() is obviously unaware that a String could be fed to a method that expects an Object (indeed, it's documentation says that it looks for method with the specified name and exactly the same formal parameter types).
Is there a straightforward way to find methods reflectively, like getMethod() does, but taking polymorphism into account, so that the above reflection example could find the print(Object) method when queried with ("print", String.class) parameters?
The reflection tutorial
suggest the use of Class.isAssignableFrom() sample for finding print(String)
Method[] allMethods = c.getDeclaredMethods();
for (Method m : allMethods) {
String mname = m.getName();
if (!mname.startsWith("print") {
continue;
}
Type[] pType = m.getGenericParameterTypes();
if ((pType.length != 1)
|| !String.class.isAssignableFrom(pType[0].getClass())) {
continue;
}
}
The easy way to do this is via java.beans.Statement or java.beans.Expression. Does all these hard yards for you.
getMethod() is obviously unaware that
a String could be fed to a method
that expects an Object
'Unaware' is a strange way to put it. getMethod() adheres to its specification. You have to supply the formal parameters, not the types of the actual arguments.
FYI, it is how I invoke method using reflection with multiple parameters without giving their types.
public class MyMethodUtils {
/**
* Need to pass parameter classes
*/
public static Object invoke(Object invoker, String methodName, Object[] parameters, Class[] parameterClasses) throws Exception {
Method method = invoker.getClass().getMethod(methodName, parameterClasses);
Object returnValue = method.invoke(invoker, parameters);
return returnValue;
}
/**
* No need to pass parameter classes
*/
public static Object invoke(Object invoker, String methodName, Object[] parameters) throws Exception {
Method[] allMethods = invoker.getClass().getDeclaredMethods();
Object returnValue = null;
boolean isFound = false;
for (Method m : allMethods) {
String mname = m.getName();
if (!mname.equals(methodName)) {
continue;
}
Class[] methodParaClasses = m.getParameterTypes();
for (int i = 0; i < methodParaClasses.length; i++) {
Class<?> parameterClass = parameters[i].getClass();
Class<?> methodParaClass = methodParaClasses[i];
boolean isAssignable = methodParaClass.isAssignableFrom(parameterClass);
if (!isAssignable) {
continue;
}
}
returnValue = m.invoke(invoker, parameters);
isFound = true;
}
if (!isFound) {
throw new RuntimeException("Cannot find such method");
}
return returnValue;
}
}
Sample Usage:
MyMethodUtils.invoke(student, "setNameAndMarks", new Object[] { "John", marks }, new Class[] { String.class, Collection.class });
MyMethodUtils.invoke(student, "setNameAndMarks", new Object[] { "John", marks });
However, for the method invoke(Object invoker, String methodName, Object[] parameters), it is possible to invoke wrong method if the signature is ambiguous. For example, if there is two methods for the invoker:
public void setNameAndMarks(String name, Collection<Integer> marks);
public void setNameAndMarks(String name, ArrayList<Integer> marks);
Passing the following parameter may invoke wrong method
setNameAndMarks("John", new ArrayList<Integer>());

Categories