Java dynamic function calling - java

I have a String array that contains names of method in the yyyyyy class
In the xxxxxx class I'm making a yyyyyy instance (say obj). Now I can call obj.function_name(), except I want to read function_name from the String array in a loop. Is this possible?

You can, using reflection. It is done by calling Yyyy.class.getMethod("methodName").invoke(someArgs)
You'd have to handle a bunch of exceptions, and your method must be public. Note that java coding conventions prefer methodName to method_name.
Using reflection, however, should be a last resort. You should be using more object-oriented techniques.
If you constantly need similar features, perhaps you can look at some dynamic language running on the java platform, like Groovy

It's possible using reflection, although you should probably question your design somewhat if you need that sort of behavior. Class.getMethod takes a String for the method name and returns a Method object, which you can then call .invoke on to call the method
These Javadoc pages should be helpful:
Class.getMethod
Method.invoke
Sample code (assuming the yyyyyy methods take one int argument, just to show argument passing):
yyyyyy obj = new yyyyyy();
String[] methodNames = {"foo", "bar", "baz"};
for(String methodName : methodNames) {
Method method = Class.forName("yyyyyy").getMethod(methodName, new Class[] {int.class});
method.invoke(obj, 4); // 4 is the argument to pass to the method
}

Related

Pass C++ object to Java vs set object parameters one by one using JNI

I have searched for this question and found a few answers but have not really found what I am looking for.
I call Java using JNI from C++ and set a Java object's fields one by one. Something like below:
jobject jSomeObject = (jobject) JVM_ENV->CallObjectMethod(myObj, getObjMethodID, "");
JVM_ENV->CallVoidMethod(jSomeObject , setMethodID1, SomeIntVal);
JVM_ENV->CallVoidMethod(jSomeObject , setMethodID2, SomeStringVal);
All parameters inside the jSomeObject are set one by one like this. And you see that there are multiple JNI calls going on which is expensive. What I am thinking is, if there is a way that I set all the parameters in the native environment and send the object just once to avoid multiple JNI calls.
Some of the posts says that it is not possible to pass a custom object to JNI. Can I do it ?
Edit:
Above calls changed to something:
jobject jSomeObject = (jobject) JVM_ENV->CallObjectMethod(myObj, getObjMethodID, "");
someClass obj = new someClass();
obj.setMethod1(someInvVal);
obj.setMethod2(someStringVal); // so on...
JVM_ENV->CallVoidMethod(jSomeObject , setMethodID1, obj);
No: You can only call methods and constructors and get and set fields that are defined in Java.
Yes: You can possibly define additional classes and methods in Java that will do what you need in one call. For example, myObj:getObjMethodID seems to be a factory method. You could add a method overload that takes all the values you want to initialize the created object with.
In general, if you can make things powerful in Java, the tasks done in JNI will be simpler.

Long commands in Java

I am learning to code in Java
I know what namespaces, classes and methods are
with that knowledge I understand code such as the following
CharSequence v = new BackwardString("whale");
v.toString();
However sometimes you see examples of code which are longer than this
an example being
dictionary.subSet("a","ab").size();
In the ubove example dictionary is a class and subSet() is a method.
However size() is also a method but methods cannot contain other methods, so where does size() come from and why does it work?
Another common example which i have used without giving any thought to until now is
System.out.printLn();
in this case would System be a namespace, out be a class and printLn() be a method?
dictionary.subSet("a","ab").size();
It's a chaining of method calls. dictionary.subSet("a","ab") returns a String object, on which you call the size method.
System.out.println()
System is a class (java.lang.System), out is a static variable of that class whose type is PrintStream, and println is a method of PrintStream.
dictionary.subSet("a","ab").size();
The subSet method returns a String object, you are then calling .size() on this String. It is shorthand for doing the following
String a = dictionary.subSet("a","ab")
int size = a.size();
System.out.println()
System.out returns a PrintStream method, and you are invoking the println() method of that object.
This is called Method Chanining
System.out.printLn();=
System is a class
PrintStream is a class again // ref is out
println() is a function
In this example:
dictionary.subSet("a","ab").size();
method subSet returns an object with method size which gets invoked after subSet returns.
Similar thing happens with another snippet:
System.out.printLn();
Class System contains a static field out which has a method println
This is a common practice in Java programming to pipeline method calls. Sometimes an object can return itself allowing you can call multiple methods in one line.
The . selection is done as follows:
(dictionary.subSet("a","ab")).size();
Set s = dictionary.subSet("a","ab");
s.size();
The method subSet delivers (likely) a Set,
and Set has a method size.
This is called "chaining".
To get a feeling of it:
BigDecimal n = BigDecimal.valueOf("123456780.12");
n = n.multiply(n).add(n).divide(BigDecimal.TWO).subtract(n);
BigDecimal does large numbers with precise fixed point arithmetic.
It cannot use operators, and the above is a normal style.
Selectors (that might be chained:
. member
[ index ]
( function arguments )

Java pass and construct class as function argument

I was using a library called Mallet. It is by far the most complicated Java Library I have ever used. They provide tutorials and code template and I was trying to understand it. However, I came across this line of code:
TransducerEvaluator evaluator = new MultiSegmentationEvaluator(
new InstanceList[]{trainingData, testingData},
new String[]{"train", "test"}, labels, labels) {
#Override
public boolean precondition(TransducerTrainer tt) {
// evaluate model every 5 training iterations
return tt.getIteration() % 5 == 0;
}
};
Please don't pay too much attention on the term "transducer". What is passed into this function? Two classes? What is this new String[]{}? I am just very very confused with this syntax as I have never seen it before.
This is the code for this method:
public MultiSegmentationEvaluator (InstanceList[] instanceLists, String[] instanceListDescriptions,
Object[] segmentStartTags, Object[] segmentContinueTags)
Can someone tell me what this weird construct is?
This construct does several things:
Creates a subclass of MultiSegmentationEvaluator without giving it a name
Provides an override of the precondition(TransducerTrainer tt) method
Instantiates the newly defined anonymous class by passing two string arrays and then labels to the constructor that takes four parameters.
Assigns the newly created instance to the evaluator variable.
The code uses the anonymous class feature of Java - a very handy tool for situations when you have to subclass or implement an interface, but the class that you define is used in only one spot in your program.
Consider this code:
String[] stringArr = new String[]{"train", "test"};
Does it make any sense now? It is a String array! =) Here's even more stupid code to prove my point:
new String[]{"train", "test"}.getClass() == String[].class
InstanceList[]
means that you need to have a list of objects that are of they type InstanceList, same goes for String[]
for these:
Object[]
means that anything that is a sublass of Object (any object) can be passed as arguments for the last two paramaters.
In the top code this is exactly what they're doing but they create new objects for InstanceList and String,and then labels is the 2 objects they're passing.

Removing compiler's warning from a method call, advise needed

As part of my Utils class, i have both
public static boolean isStringEmptyOrNull(String... s) {
When testing for a null condition
assertTrue(Utils.isStringEmptyOrNull(null));
I get "The argument of type null should explicitly be cast to String[] for the invocation of the varargs method isStringEmptyOrNull(String...) from type Utils. It could alternatively be cast to String for a varargs invocation" warning.
I'd rather not case anything though. This test is designed to simulate a condition where argument passed to the method is a null.
Is there a way to remove this warning without changing the signature of the method?
You should probably test both of these cases:
assertTrue(Utils.isStringEmptyOrNull(new String[] { null }));
assertTrue(Utils.isStringEmptyOrNull((String[]) null));
... although it's not clear to me why a method which sounds like it should only take a single string is taking an array of strings in the first place, to be honest.
(Is it obvious to you which of those invocations you meant without the cast? It isn't obvious to me... I'd have to look it up to check.)
If you are trying to mimic the way a client of your library function would call your code, you should take advantage of the fact that they will not call this particular method with the literal "null" (what would be the point?)
Instead, they would pass in some variable or expression. Since that's the case, you can do something like this and avoid casting:
String nullString = null;
assertTrue(Utils.isStringEmptyOrNull(nullString));
You could specifically tell the compiler to ignore the warning using #SuppressWarnings("all").
Well that warning's there for a reason: when you call your method with null argument, since null is all and any type in Java (including Array), the compiler effectively will not know if you're calling the var-args method with an array or a non-array object (each of which is treated differentlly when var-args arguments are used). What you can do is annotate the method with SuppressWarnings("All") and then test for null before doing anything with the argument(s)
Change your test like so:
String nullString = null;
assertTrue(Utils.isStringEmptyOrNull(nullString));
Rather curious why you use a vararg method for this in the first place though...

Calling closest fitting method

As part of developing a small ScriptEngine, I reflectively call java methods. A call by the script engine gives me the object the method name and an array of arguments. To call the method I tried to resolve it with a call to Class.getMethod(name, argument types).
This however only works when the classes of the arguments and the classes expected by the Method are the same.
Object o1 = new Object();
Object out = System.out;
//Works as System.out.println(Object) is defined
Method ms = out.getClass().getMethod("println",o1.getClass());
Object o2 = new Integer(4);
//Does not work as System.out.println(Integer) is not defined
Method mo = out.getClass().getMethod("println",o2.getClass());
I would like to know if there is a "simple" way to get the right method, if possible with the closest fit for the argument types, or if I have to implement this myself.
Closest fit would be:
Object o1 = new Integer(1);
Object o2 = new String("");
getMethod(name, o1.getClass())//println(Object)
getMethod(name, o2.getClass())//println(String)
Update:
To clarify what I need:
The Script Engine is a small project I write in my free time so there are no strikt rules I have to follow. So I thought that selecting methods called from the Engine the same way the java compiler selects methods at compile time only with the dynamic type and not the static type of the Object would work.(with or without autoboxing)
This is what I first hoped that the Class.getMethod() would solve. But the Class.getMethod() requires the exact same Classes as argument types as the Method declares, using a subclass will result in a no such method Exception. This may happen for good reasons, but makes the method useless for me, as I don't know in advance which argument types would fit.
An alternate would be to call Class.getMethods() and iterate through the returned array and try to find a fitting method. This would however be complicated if I don't just want to take the first "good" method which I come across, so I hoped that there would be an existing solution which at least handles:
closest fit: If arg.getClass() ==
subclass and methods m(Superclass),
m(Subclass) then call m(Subclass)
variable arguments:
System.out.printf(String ,String...)
Support for autoboxing would be nice, too.
If a call cannot be resolved it may throw an exception ( ma(String,Object), ma(Object, String), args= String,String)
(If you made it till here, thanks for taking the time to read it:-))
As others have pointed out there is no standard method that does this, so you are going to have to implement your own overload resolution algorithm.
It would probably make sense to follow javac's overload resolution rules as closely as possible:
http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#292575
You can probably ignore generics for a dynamically-typed scripting language, but you might still benefit from the bridge methods that the compiler generates automatically.
Some pitfalls to watch out for:
Class.isAssignableFrom does not know about automatic widening primitive conversions, because these are syntactic sugar implemented in the compiler; They do not occur in the VM or class hierarchy. e.g. int.class.isAssignableFrom(short.class) returns false.
Similarly Class.isAssignableFrom does not know about auto-boxing. Integer.class.isAssignableFrom(int.class) returns false.
Class.isInstance and Class.cast take an Object as an argument; You cannot pass primitive values to them. They also return an Object, so they cannot be used for unboxing ((int) new Integer(42) is legal in Java source but int.class.cast(new Integer(42)) throws an exception.)
I would suggest that you use getMethods(). It returns an array of all public methods (Method[]).
The most important thing here is:
"If the class declares multiple public member methods with the same parameter types, they are all included in the returned array."
What you will then need to do is to use the results in this array to determine which one of them (if any) are the closest match. Since what the closest match should be depends very much on your requirements and specific application, it does make sense to code it yourself.
Sample code illustrating one approach of how you might go about doing this:
public Method getMethod(String methodName, Class<?> clasz)
{
try
{
Method[] methods = clasz.getMethods();
for (Method method : methods)
{
if (methodName.equals(method.getName()))
{
Class<?>[] params = method.getParameterTypes();
if (params.length == 1)
{
Class<?> param = params[0];
if ((param == int.class) || (param == float.class) || (param == float.class))
{
//method.invoke(object, value);
return method;
}
else if (param.isAssignableFrom(Number.class))
{
return method;
}
//else if (...)
//{
// ...
//}
}
}
}
}
catch (Exception e)
{
//some handling
}
return null;
}
In this example, the getMethod(String, Class<?>) method will return a method that with only one parameter which is an int, float, double, or a superclass of Number.
This is a rudimentary implementation - It returns the first method that fits the bill. You would need to extend it to create a list of all methods that match, and then sort them according to some sort of criteria, and return the best matching method.
You can then take it even further by creating the more general getMethod(String, Class<?>) method, to handle more of the possible "close match" scenarios, and possibly even more than one paramter
HTH
Edit: As #finnw has pointed out, be careful when using Class#isAssignableFrom(Class<?> cls), due to its limitations, as I have in my sample code, testing the primitives separately from the Number objects.
AFAIK, there is no simple way to do this kind of thing. Certainly, there's nothing in the standard Java class libraries to do this.
The problem is that there is no single "right" answer. You need to consider all of your use-cases, decide what the "right method" should be and implement your reflection code accordingly.

Categories

Resources