In the following code if retString is a method name , then how do I pass a parameter to that method if it has one?
You need a Method object to invoke methods. And then use the invoke() method of the Method class to well, invoke the method you intend to run. And there you pass parameters, like:
Object o = m.invoke(t, new Locale(args[1], args[2], args[3]));
( that is a snippet from the official documentation )
Related
I'm trying to capture a parameter passed in input to a mock object with PowerMockito, this is the code:
//I create a mock object
ClassMocked mock = PowerMockito.mock(ClassMocked.class);
//Create the captor that will capture the String passed in input to the mock object
ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
//When the method put is executed on my mock I want the second parameter (that is a String) to be captured
Mockito.verify(mock).put(anyString(), inputDataMapCaptor.capture());
//Creates the instance of the class that I want to test passing the mock as parameter
ClassToTest instance = new ClassToTest(mock);
//Executes the method that I want to test
instance.methodToTest();
/* I know that during the execution of "methodToTest()" mock.put(String,String) will be executed and I want to get the second string parameter. */
When I execute the test I have an exception executing the line Mockito.verify(mock).put(...);
"Wanted but not invoked mock.put(any,Capturing argument);"
What is wrong?
You should call instance.methodToTest(); before Mockito.verify(mock).put(anyString(), inputDataMapCaptor.capture());
verify() verifies that the specified method call did take place.
You can't verify "upfront" that a method call is supposed to happen.
Thus: verify() needs to happen after the facts, not before!
I want to do something different with java reflection. The program i written to add global listeners to java components when applets are opened from browser. An event fired and i get event source object. Here i don't know the actual class name that object referring to.
if(object.getClass.getName().contains("oracle.ewt.laf.basic.BasicTabBarUI$Menu"))
{
// here we can invoke methods,fields,etc using reflection
}
I can call the methods of BasicTabBarUI$Menu class with reflection.
Suppose now i have the following lines with me in the above if block
LWMenuItem menuItem = (LWMenuItem)object;
menuItem.getLabel());
I don't want to specify LWMenuItem class name , instead i want to call its method getLabel(). If we know the class name , we can do as above. But how can we do same with reflection. How can we do casting in reflection?
You don't need to do casting, except of the result of calling the method. Just use the object's Class object, which has a getMethod method that will return a Method object for the method you want, then invoke it:
Class cls = object.getClass();
Method getLabel = cls.getMethod("getLabel", null);
String label = (String)getLabel.invoke(object, null);
You can continue working with the basic object when using the return value from getLabel():
Method getLabelMethod = object.getClass().getMethod("getLabel");
Object menuItem = getLabelMethod.invoke(object);
menuItem.getClass().getMethod("getName").invoke(menuItem); // or whatever...
SubArray = Key.Ikey;
Ikey being the variable which holds the name of the method.
I tried:
SubArray = Key.(this.IKey);
but the compiler gave the error identifier excpected.
I think you are interested in reflection. It goes something like:
method = object.getClass().getMethod(methodName, param1.class, param2.class, ..);
So you are calling the method specified by the variable 'methodName' of the object 'object'
You can read more here Reflection
and in this tutorial link
I'm having some trouble using reflection in Java. I'm attempting to save a method of a data structure but getting an error. The error is
java.lang.NoSuchMethodException: cs671.eval.SerialList.add(java.lang.Integer, java.lang.String)
The method, in this case, that I'm trying to get is the add method for a SerialList that takes a Comparable and an Object as its parameters.
structType = "cs671.eval.SerialList", keyType = "java.lang.Integer", and valType = "java.lang.String" are strings that were read in from a file.
Class dataClass = null, comparableClass = null, objectClass = null;
try{ // create data structure
dataClass = Class.forName(structType);
comparableClass = Class.forName(keyType);
objectClass = Class.forName(valType);
}
catch(ClassNotFoundException e){}
java.lang.Object structObj = null;
try{ // Create a data structure object
structObj = dataClass.newInstance();
}
catch(Exception e){}
Method m = null;
try{ // Attempt to get add method for the data structure
m = dataClass.getMethod("add", comparableClass, objectClass); // This is where it fails
}
catch(Exception e){}
Basically I'm trying to get the right method on the right datastructure with the correct classes that are going to get passed into that method but I don't know how to tell the getMethod method that those classes (comparableClass and objectClass) are the correct ones.
Thanks in advance!
Added: Here's the SerialList's add method signature
public void add(java.lang.Comparable, java.lang.Object)
You are saying -
The method, in this case, that I'm trying to get is the add method for a SerialList that takes a Comparable and an Object as its parameters.
But passing the classes - java.lang.Integer, java.lang.String.
Just a note - Only public methods are visible to getMethod() for non-publics you would have to use getDeclaredMethod() instead.
From http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#getMethod%28java.lang.String,%20java.lang.Class...%29:
To find a matching method in a class C: If C declares exactly one public method with the specified name and exactly the same formal parameter types, that is the method reflected. If more than one such method is found in C, and one of these methods has a return type that is more specific than any of the others, that method is reflected; otherwise one of the methods is chosen arbitrarily.
=> You need to pass java.lang.Comparable.class & java.lang.Object.class
Apologies for providing wrong answer earlier. Based on your comments it appears that you're trying to get a Method by avoiding to provide specific parameter types needed in the signature of that method.
If my understanding is correct then you should rather use Class#getMethods() and examine the returned Method[] for your method. Consider a skeleton code like this:
Method[] methods = dataClass.getMethods();
boolean matched = false;
// find a matching method by name
for (Method method: methods) {
Class<?>[] parameterTypes = method.getParameterTypes();
if ( "add".equals(method.getName()) && parameterTypes.length == 2 ) {
// method is your target method
// however you'll need more strict checks if there can be another add method
// in your class with 2 different parameter types
}
}
As other answers have stated, to use getMethod() you need to know and use the actual declared formal parameters of the method you are attempting to retrieve.
However, if for some reason you do not know the formal parameters at compile time, then you can iterate over all of the methods from the class until you find a method that fits your parameters (or find the most specific method that fits your parameters).
There is functionality written to do this already in apache commons bean utils, specifically in org.apache.commons.beanutils.MethodUtils.invokeMethod(...) and MethodUtils.getMatchingAccessibleMethod(...).
Source code for the above methods can be easily viewed online here.
I have a method which I am trying to call dynamically. That method has an argument 'stringValue'. The method I am trying to invoke is in the parent (receivers??) class.
I can't figure out how to get the reference back to the parent
java.lang.reflect.Method method;
method = Class.forName("com.blah.MyActivity").getMethod("myFunction", String.class);
method.invoke(this,stringValue);
Gives the error:
'Message expected receiver of type com.blah.MyActivity, but got com.blah.MyActivity$SubTask'
I suspect you want:
method.invoke(MyActivity.this, stringValue);
The MyActivity.this part is the way of getting to the enclosing instance of MyActivity.
See section 15.8.4 of the JLS for more details.