If I have function names stored as strings in a Hashtable.
Is there a way to access the functions via the stored strings?
EDIT
I'm afraid the platform that i'm working on CLDC1.1/MIDP2.0 does not support Reflection.
Any workaround possible?
If I have function names stored as strings in a Hashtable.
Is there a way to access the functions via the stored strings?
EDIT
I'm afraid the platform that i'm working on CLDC1.1/MIDP2.0 does not support Reflection.
Any workaround possible?
Given a function name, you could use reflection to access the method. Besides the name of the function, you need to know its class, and have (or create via reflection if it has a noarg constructor or you know what parameters to pass to the constructor) an instance (if the method is not static) and you have to know the parameters required to pass to it.
Another option is to use the Method class as a pointer to the function. It has the advantage of knowing its class, and knowing its parameter requirements. It has the disadvantage of not being serializable.
EDIT: There is no way to access a method in Java without reflection by just having its name as a string. If you want an alternative pointer to a method, you could use an anonymous inner class that invokes the method you want that implements a known interface and pass that to your map. That would not be appropriate as the key of the map, but it would work as a value in the map.
I haven't tried reflection on javame, but on javase you can use reflection to dynamically call a method.
The following snippet is taken from: http://java.sun.com/developer/technicalArticles/ALT/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);
}
}
}
EDIT: Rather than using if..then..else you may want to actually pass back a number, and use a switch, as it will be easier to read, IMO.
But, regardless, that is probably your only option given the limitations of JavaME.
Just use a big long list of else-ifs:
[...]
} else if ("foo".equals(function)) {
target. foo();
} else if ("bar".equals(function)) {
target. bar();
[...]
(Although I generally don't like attempting vertical alignments in source, I think in cases like this it is well worth it.)
Storing a functor in the map is an alternative, bu might increase object size too much for many MIDP applications.
Class.forName() and newInstance() should be there on MIDP 1.1 and might be useful. Since you don't have full reflection, you could create a class that wraps all the function calls and invokes them. This assumes you know all the function calls in advance.
You'll need references to all the objects unless you're doing static calls. Kinda messy, but would get the job done.
public Object invoke(String name, Object[] args) {
Object f = functionMap.get(name);
if("f1".equals(name)) {
return ((SomeInterface1)f).someFunction1((SomeArg0) args[0]), ...);
} else if ("f2".equals(name)) {
return ((SomeInterface2)f).someFunction2((SomeArg0) args[0]), ...);
}...{
} else if ("fN".equals(name)) {
return ((SomeInterfaceN)f).someFunctionN((SomeArg0) args[0]), ...);
}
}
I deal with similar issues in Hecl, an interpreter that runs on J2ME. It sort of depends on how many strings you want to deal with, but one method that works is to use the hash to look up an integer, and then use that in a switch statement, instead of the big list of if/then statements. By the way, you're welcome to use the Hecl source code; it's available under the liberal Apache license.