I'm wanting to use Java reflection to call a method on a class of mine that has the following signature:
public Object execute(Object...params)
In my loader class, I have the class loaded, but I'm not sure how to setup my getMethod call. Currently, I have something like this:
Method classEntry = _loadedClass.getMethod("execute", new Class[]{Object[].class});
I then try to invoke this method after creating a newInstance of my class by calling:
Object classObj = _loadedClass.newInstance();
classEntry.invoke(classObj, params); // params comes in from the method as Object...params
This is giving me a java.lang.NoSuchMethodException Exception. I know that my issue lies in my getMethod call. How should I set that up to accept a params object?
If params is of type Object [] then you need to call invoke like this:
classEntry.invoke(classObj, new Object [] {params});
But this does not explain NoSuchMethodException
Related
WeatherDataModel weatherDataModel = new WeatherDataModel.fromJson(response);
I am creating a WeatherDataModel(my second class) object using the method fromJson ( defined in WeatherDataModel class) in my MainActivity using the parameters response.
But when I write above code Android studio can't recognize fromJson, but when I write this:
WeatherDataModel weatherDataModel = new WeatherDataModel();
weatherDataModel.fromJson(response);
It doesn't show any error.
Is there's a difference between these 2 lines?
You need an instance of an object before call a method,
so you code should be like this.
WeatherDataModel weatherDataModel = new WeatherDataModel().fromJson(response);
Either you missed the brackets for the constructor or you can even get rid of the new keyword by declaring the fromJson method static, which would make even more sense from a point of readability of the code.
If fromJson is not static, it can be called on a living instance at any time, destroying any values already stored in that instance.
So I'd declare that method as
public static WeatherDataModel fromJson(String response) {
WeatherDataModel wd = new WeatherDataModel();
// parse your response into wd's fields
return wd;
}
and from outside your call then looks like
WeatherDataModel model = WeatherDataModel.fromJson(response);
Hope this helps, cheers
I've seen a lot of examples, and I know what has been discussed.
I do everything right, but I receive an error. Why is that? What am i doing wrong?
Class superClass = rootObject.getSuperclass();
Method addErrorMethod = superClass.getDeclaredMethod("addErrorMessage", ErrorType.class, String.class, String.class, String.class);
_log.info(addErrorMethod.getName());
addErrorMethod.invoke(superClass, ErrorType.FIELD, propertyName, message, "");
I get method, but when you call the invoker. I get the following error.
java.lang.IllegalArgumentException: object is not an instance of declaring class
Thanks.
When you call Method.invoke the first parameter must be either:
when method is non-static instance of the class which contains the method
when method is static null or class itself.
Since you pass the class itself and you got error it suggests that method you are trying to invoke is not static, so you should invoke it like
addErrorMethod.invoke(rootObject, ErrorType.FIELD, propertyName, message, "");
// ^^^^^^^^^^- assuming it is instance on which we want to invoke this method
You did not do everything right:
addErrorMethod.invoke(superClass, ErrorType.FIELD, propertyName, message, "");
should read
addErrorMethod.invoke(rootObject, ErrorType.FIELD, propertyName, message, "");
superClass is an instance of Class, to which has no addErrorMessage() method, as the error message is telling you. The first parameter to the method is a reference to the object that will be used as this within the method.
I'd like to call via reflection the following method, but I have problem to specify the correct signature:
public void executeRule(List<Node> params, SomethingStrangeFound callMeBack) throws IOException
{
...
}
I tried something like this:
Class partypes[] = new Class[2];
partypes[0] = Class.forName("java.util.List");
partypes[1] = Class.forName("vp.SomethingStrangeFound");
Method meth = cls.getMethod("executeRule", partypes);
It doesn't work because I use "java.util.List" when it must be "List<Node>", but I have no idea how to specify it.
If I just use "java.util.List", I have the following error calling cls.getMethod("executeRule", partypes):
NoSuchMethodException: vp.RuleWebXmlContextParamFacesPortletRenderStyles.executeRule(java.util.List, vp.SomethingStrangeFound)
Any help?
P.S.
At debug time, I see "List<Node>" is resolved with:
(Ljava/util/List<Lorg/w3c/dom/Node;>;Lit/vp/SomethingStrangeFound;)V
but it doesn't help me.
If both parameter classes are available at compile time you can initialize parameter array like this:
Class partypes[] = new Class[] { List.class, SomethingStrangeFound.class };
Method meth = cls.getMethod("executeRule", partypes);
This will guarantee that you have not mistyped qualified class names.
If this still does not work, check available methods in your class using Class#getMethods() method:
for (Method method : cls.getMethods()) {
System.out.println(method);
}
I ran your code and it worked for me.
You have not provided the definition of cls, but I assume it is something like
Class cls = RuleWebXmlContextParamFacesPortletRenderStyles.class;
Since you get a NoSuchMethodException, Class.forName already passed successfully, so no typo there (unless you have multiple SomethingStrangeFound classes, which would mean that you got the package wrong).
Because of this the last thing that comes to my mind is that perhaps you compiled RuleWebXmlContextParamFacesPortletRenderStyles before adding the method in question. Clean your code and recompile.
With partypes of size 2, getMethod will search for a method called "executeRule" with 2 parameters, one of type "java.util.list" and other of type "vp.SomethingStrangeFound"
But your method has only 1 parameter. You need to add a second parameter of type "vp.SomethingStrangeFound" to your method or set partypes size to 1.
This question is being asked everywhere on Google but I'm still having trouble with it. Here is what I'm trying to do. So like my title states, I'm getting an 'object is not an instance of declaring class' error. Any ideas? Thanks!
Main.java
Class<?> base = Class.forName("server.functions.TestFunction");
Method serverMethod = base.getMethod("execute", HashMap.class);
serverMethod.invoke(base, new HashMap<String, String>());
TestFunction.java
package server.functions;
import java.util.HashMap;
import java.util.Map;
import server.*;
public class TestFunction extends ServerBase {
public String execute(HashMap<String, String> params)
{
return "Test function successfully called";
}
}
You're invoking the method with the class, but you need an instance of it. Try this:
serverMethod.invoke(base.newInstance(), new HashMap<String, String>());
You are trying to invoke the execute method on the object base, which is actually a Class object returned by your Class.forName() call.
This would work for a static (class) method - but execute is a non-static (instance) method.
(It would also work for calling an instance method of an object of type Class - but that's not what you are trying to achieve here!)
You need an actual instance of TestFunction to invoke the method on, or you need to make the method static.
When invoking a static method by reflection, the first argument to invoke() is ignored, so it is conventional to set it to null, which clarifies the fact that there's no instance involved.
Although your current example method would do the same thing for any TestFunction object, in general an instance method could produce a different result for each object - so the .invoke() reflection method needs to know which object to run the method on.
I have met some tutorials on the web, which are invoking simple methods and all I need is to invoke method "startDownload" which accepts Context as a parameter. I am now calling it:
Class<?> loaded = cl.loadClass("com.test.someclass");
Method m = loaded.getDeclaredMethod("startDownload", null);
m.invoke(this, null);
where c1 is DexClassLoader. But no success. I am getting error of NoSuchMethodException, I know I have to add parametres somewhere, but don't know where... any advices?
Thanks
I suggest looking at that post.
The parameters are passed after the method name when calling Class.getMethod(name, ...), as described here. You can directly use the class member of the Class you have to pass:
Method myMethod = myClass.getMethod("doSomethingWithAString", String.class);
Maybe you forgot some of them: the method won't be found if the signature (so the parameters) are not correct.