Efficient way to convert unknown objects to appropriate Method.invoke arguments? - java

I'm writing a reflection-based RPC service that gets arguments passed in via a variety of mechanisms. Sometimes the arguments correctly match the parameter type, sometimes they're always strings, and sometimes they're wrapped up in dynamically typed "scripty" objects that need the appropriate value extracted out.
Before I can call method.invoke, I need to build the argument list, something like this:
Object a[] = new Object[method.parameterClasses.length];
for (int i = 0; i < a.length; ++i)
{
a[i] = prepare(method.parameterClasses[i], rpc.arguments[i]);
}
The "prepare" method looks something like:
Object prepare(Class clazz, Object o)
{
if (o == null) return null;
if (clazz == o.getClass()) return o;
if (clazz == String.class) return o.toString();
// skip a bunch of stuff for converting strings to dates and whatnot
// skip a bunch of stuff for converting dynamic types
// final attempts:
try
{
return clazz.cast(o);
}
catch (Exception e)
{
return o; // I give up. Try the invoke and hope for the best!
}
}
During unit testing, I was recently rather surprised to discover that a method passed a boxed Integer that expected a primitive long was actually failing the cast and falling through the bottom, and then being properly converted by something during the invoke(). I'd assumed the call to "cast" would do the trick. Is there any way to explicitly perform and check the argument conversion done normally by invoke?
Lacking that, I thought about putting in explicit checks for numeric types, but the number of permutations seemed out of hand. When I add support for extracting numbers from the script dynamic types and converting strings, it gets even worse. I envision a bunch of conditional typechecks for each possible numeric target class, with Integer.decode, Long.decode etc for the String arguments, Short.decode, and Number.intValue, Number.longValue, etc. for Numbers.
Is there any better way to do this whole thing? It seemed like a good approach at first, but it's getting pretty yucky.

It is indeed surprising, but that is the current behavior. See bug 6456930.
In terms of a better way to approach the problem, at its core, no you will have to define all of those rules. There are better (more maintainable) patterns that a series of if's, though. For starters, I'd have some strategy objects that can be invoked for one side of those objects (probably the class side) so that you look up the appropriate object (say from a Map) based on the class, and then you can limit your conversions to one side (each object would be concerned about how to get things into that particular class). That way when there is a new kind of class conversion that you need to support, you can write an object for it, test it separately and just plug it into the map without changing further code.

There's really not a better way. There are an infinite number of potential conversions, but only a tiny number that really make sense. Rather than trying to give clients complete freedom, I recommend specifying a contract for type coercion.
As a starting point, check out the type conversion rules used by the JSP Expression Language. They are quite powerful, and allow many types of conversions to take place, but they are also well-defined, easy to remember—and possible to implement.

There are at least a few shortcuts you can take to simplify your code:
If the parameter is an instance of java.lang.Number and the argument type is either byte, short, int, long, float or double (either as primitive, or as wrapper class), you can use the methods in Number like byteValue(), shortValue(), etc to convert the parameter.
If the parameter is an instance of java.lang.String and the argument type is one of the above mentioned, you can use the static valueOf(String) method in the respective class for conversion.
Converting further, and perhaps even proprietary types would of course need more work. If it's really necessary and your prepare method is getting to large, you should perhaps consider abstracting the conversion behind an interface and allowing pluggable conversion providers to be dynamically added to the application?

Related

Java Best Practices - Returning an Object vs. a Generic

I'm using Generics for the first time for a school project and I have come across a philosophical dilemma regarding whether to return objects or my declared generic element in my methods.
My OCD is telling me that I need to always return the known type but I'm finding that doing so creates some downstream annoyances when I feed primitive datatypes into my class (and, of course, for this project I'm only ever feeding primitives into this class).
Here's an example of what I mean:
public class DansPriorityQueue<E extends Comparable>
{
private ArrayList<E> tree;
//Here's a method that returns an object
public Object peek() {
return tree.get(0);
}
//Here's a method that returns the generic type
public E peek() {
return tree.get(0);
}
(As an FYI.. I'm required to implement this JDK class myself but I am fortunately not required to implement the same interfaces that the real PriorityQueue does so I do have a choice as to whether I want to use the Object or the generic)
My Issue
It makes me feel a little dirty but I'm tempted just to return an Object rather than my E generic element on these methods because when I return E, JUnit forces me to cast my integer values:
DansPriorityQueue<Integer> dpq = new DansPriorityQueue<Integer>();
dpq.add(1);
assertEquals("Expected different value", (Integer) 1, dpq.peek());
When I return an object on the other hand, the auto-boxing doesn't force me cast my primitive value.
Here's a more eloquent description of the issue I've been facing:
http://www.aschroder.com/2009/10/php-1-java-0-the-method-assertequalsobject-object-is-ambiguous-for-the-type/
------------EDIT----------------
Here's the actual error I receive when I return the generic type and fill my list with the autoboxed Integer object without the cast above: The method assertEquals(String, Object, Object) is ambiguous for the type DansPriorityQueueTest
--------- END EDIT--------------
Questions
Can anyone tell me why I should or should not return an object as opposed to the generic element I'm working with? Both seem to have upsides and downsides... what's the best practice?
I know vaguely that returning an Object can cause some casting issues later on but I've not yet run into them... does anyone have a specific example of how this can be dangerous?
In the JDK, I've noticed that many of the Collections methods return Object by default. Is this because Generics was introduced in a later version of Java or was this a conscious decision by Sun Systems?
Can anyone tell me why I should or should not return an object as opposed to the generic element I'm working with? Both seem to have upsides and downsides... what's the best practice?
It depends. In a case like this you'd want to generic type - otherwise what's the point of defining generic type for the class?
I know vaguely that returning an Object can cause some casting issues later on but I've not yet run into them... does anyone have a specific example of how this can be dangerous?
Sure!
DansPriorityQueue<String> queue = new DansPriorityQueue<String>();
//add items
Float f = (Float)queue.getObject(); //uh-oh! this compiles but will fail
Float f = queue.getObject(); //generic type, fails during compile
In the JDK, I've noticed that many of the Collections methods return Object by default. Is this because Generics was introduced in a later version of Java or was this a conscious decision by Sun Systems?
It's due to backward compatibility mostly, or for cases where you truly will use the collection to contain disparate values (a mishmash of say, JLabels, Strings and Icons for instance for rendering a JTable for instance).
assertEquals("Expected different size", (Integer) 2, dpq.size());
I don't think this should be a problem. dpq.size() should just return an int regardless off what is stored in the priority queue. It would not be a generic value.
You can create something like
DansPriorityQueue<Double> queue = new DansPriorityQueue<Double>();
for(double d = 0; d < 10; d+=1.0)
queue.add(d);
and that should cause no issues, right?

OO strategy to match a set of tokens to an appropriate method / constructor

This question isn't specifically about performing tokenization with regular expressions, but more so about how an appropriate type of object (or appropriate constructor of an object) can be matched to handle the tokens output from a tokenizer.
To explain a bit more, my objective is to parse a text file containing lines of tokens into appropriate objects that describe the data. My parser is in fact already complete, but at present is a mess of switch...case statements and the focus of my question is how I can refactor this using a nice OO approach.
First, here's an example to illustrate what I'm doing overall. Imagine a text file that contains many entries like the following two:
cat 50 100 "abc"
dog 40 "foo" "bar" 90
When parsing those two particular lines of the file, I need to create instances of classes Cat and Dog respectively. In reality there are quite a large number of different object types being described, and sometimes different variations of numbers of arguments, with defaults often being assumed if the values aren't there to explicity state them (which means it's usually appropriate to use the builder pattern when creating the objects, or some classes have several constructors).
The initial tokenization of each line is being done using a Tokenizer class I created that uses groups of regular expressions that match each type of possible token (integer, string, and a few other special token types relevant to this application) along with Pattern and Matcher. The end result from this tokenizer class is that, for each line it parses, it provides back a list of Token objects, where each Token has a .type property (specifying integer, string, etc.) along with primitive value properties.
For each line parsed, I have to:
switch...case on the object type (first token);
switch on the number of arguments and choose an appropriate constructor
for that number of arguments;
Check that each token type is appropriate for the types of arguments needed to construct the object;
Log an error if the quantity or combination of argument types aren't appropriate for the type of object being called for.
The parser I have at the moment has a lot of switch/case or if/else all over the place to handle this and although it works, with a fairly large number of object types it's getting a bit unwieldy.
Can someone suggest an alternative, cleaner and more 'OO' way of pattern matching a list of tokens to an appropriate method call?
The answer was in the question; you want a Strategy, basically a Map where the key would be, e.g., "cat" and the value an instance of:
final class CatCreator implements Creator {
final Argument<Integer> length = intArgument("length");
final Argument<Integer> width = intArgument("width");
final Argument<String> name = stringArgument("length");
public List<Argument<?>> arguments() {
return asList(length, width, name);
}
public Cat create(Map<Argument<?>, String> arguments) {
return new Cat(length.get(arguments), width.get(arguments), name.get(arguments));
}
}
Supporting code that you would reuse between your various object types:
abstract class Argument<T> {
abstract T get(Map<Argument<?>, String> arguments);
private Argument() {
}
static Argument<Integer> intArgument(String name) {
return new Argument<Integer>() {
Integer get(Map<Argument<?>, String> arguments) {
return Integer.parseInt(arguments.get(this));
}
});
}
static Argument<String> stringArgument(String name) {
return new Argument<String>() {
String get(Map<Argument<?>, String> arguments) {
return arguments.get(this);
}
});
}
}
I'm sure someone will post a version that needs less code but uses reflection. Choose either but do bear in mind the extra possibilities for programming mistakes making it past compilation with reflection.
I have done something similar, where I have decoupled my parser from code emitter, which I consider anything else but the parsing itself. What I did, is introduce an interface which the parser uses to invoke methods on whenever it believes it has found a statement or a similar program element. In your case these may well be individual lines you have shown in the example in your question. So whenever you have a line parsed you invoke a method on the interface, an implementation of which will take care of the rest. That way you isolate the program generation from parsing, and both can do well on their own (well, at least the parser, as the program generation will implement an interface the parser will use). Some code to illustrate my line of thinking:
interface CodeGenerator
{
void onParseCat(int a, int b, String c); ///As per your line starting with "cat..."
void onParseDog(int a, String b, String c, int d); /// In same manner
}
class Parser
{
final CodeGenerator cg;
Parser(CodeGenerator cg)
{
this.cg = cg;
}
void parseCat() /// When you already know that the sequence of tokens matches a "cat" line
{
/// ...
cg.onParseCat(/* variable values you have obtained during parsing/tokenizing */);
}
}
This gives you several advantages, one of which being that you do not need a complicated switch logic as you have determined type of statement/expression/element already and invoke the correct method. You can even use something like onParse in CodeGenerator interface, relying on Java method overriding if you want to always use same method. Remember also that you can query methods at runtime with Java, which can aid you further in removing switch logic.
getClass().getMethod("onParse", Integer.class, Integer.class, String.class).invoke(this, catStmt, a, b, c);
Just make note that the above uses Integer class instead of the primitive type int, and that your methods must override based on parameter type and count - if you have two distinct statements using same parameter sequence, the above may fail because there will be at least two methods with the same signature. This is of course a limitation of method overriding in Java (and many other languages).
In any case, you have several methods to achieve what you want. The key to avoid switch is to implement some form of virtual method call, rely on built-in virtual method call facility, or invoke particular methods for particular program element types using static binding.
Of course, you will need at least one switch statement where you determine which method to actually call based on what string your line starts with. It's either that or introducing a Map<String,Method> which gives you a runtime switch facility, where the map will map a string to a proper method you can call invoke (part of Java) on. I prefer to keep switch where there is not substantial amount of cases, and reserve Java Maps for more complicated run-time scenarios.
But since you talk about "fairly large amount of object types", may I suggest you introduce a runtime map and use the Map class indeed. It depends on how complicated your language is, and whether the string that starts your line is a keyword, or a string in a far larger set.

Passing dynamic list of primitives to a Java method

I need to pass a dynamic list of primitives to a Java method. That could be (int, int, float) or (double, char) or whatever. I know that's not possible, so I was thinking of valid solutions to this problem.
Since I am developing a game on Android, where I want to avoid garbage collection as much as possible, I do not want to use any objects (e.g. because of auto boxing), but solely primitive data types. Thus a collection or array of primitive class objects (e.g. Integer) is not an option in my case.
So I was thinking whether I could pass a class object to my method, which would contain all the primitive vales I need. However, thats neither a solution to my problem, because as said the list of primitives is variable. So if I would go that way in my method I then don't know how to access this dynmic list of primitives (at least not without any conversion to objects, which is what I want to avoid).
Now I feel a bit lost here. I do not know of any other possible way in Java how to solve my problem. I hope that's simply a lack of knowledge on my side. Does anyone of you know a solution without a conversion to and from objects?
It would perhaps be useful to provide some more context and explain on exactly what you want to use this technique for, since this will probably be necessary to decide on the best approach.
Conceptually, you are trying to do something that is always difficult in any language that passes parameters on a managed stack. What do you expect the poor compiler to do? Either it lets you push an arbitrary number of arguments on the stack and access them with some stack pointer arithmetic (fine in C which lets you play with pointers as much as you like, not so fine in a managed language like Java) or it will need to pass a reference to storage elsewhere (which implies allocation or some form of buffer).
Luckily, there are several ways to do efficient primitive parameter passing in Java. Here is my list of the most promising approaches, roughly the order you should consider them:
Overloading - have multiple methods with different primitive arguments to handle all the possible combinations. Likely to be the the best / simplest / most lightweight option if there are a relatively small number of arguments. Also great performance since the compiler will statically work out which overloaded method to call.
Primitive arrays - Good way of passing an arbitrary number of primitive arguments. Note that you will probably need to keep a primitive array around as a buffer (otherwise you will have to allocate it when needed, which defeats your objective of avoiding allocations!). If you use partially-filled primitive arrays you will also need to pass offset and/or count arguments into the array.
Pass objects with primitive fields - works well if the set of primitive fields is relatively well known in advance. Note that you will also have to keep an instance of the class around to act as a buffer (otherwise you will have to allocate it when needed, which defeats your objective of avoiding allocations!).
Use a specialised primitive collection library - e.g. the Trove library. Great performance and saves you having to write a lot of code as these are generally well designed and maintained libraries. Pretty good option if these collections of primitives are going to be long lived, i.e. you're not creating the collection purely for the purpose of passing some parameters.
NIO Buffers - roughly equivalent to using arrays or primitive collections in terms of performance. They have a bit of overhead, but could be a better option if you need NIO buffers for another reason (e.g. if the primitives are being passed around in networking code or 3D library code that uses the same buffer types, or if the data needs to be passed to/from native code). They also handle offsets and counts for you which can helpful.
Code generation - write code that generates the appropriate bytceode for the specialised primitive methods (either ahead of time or dynamically). This is not for the faint-hearted, but is one way to get absolutely optimal performance. You'll probably want to use a library like ASM, or alternatively pick a JVM language that can easily do the code generation for you (Clojure springs to mind).
There simply isn't. The only way to have a variable number of parameters in a method is to use the ... operator, which does not support primitives. All generics also only support primitives.
The only thing I can possibly think of would be a class like this:
class ReallyBadPrimitives {
char[] chars;
int[] ints;
float[] floats;
}
And resize the arrays as you add to them. But that's REALLY, REALLY bad as you lose basically ALL referential integrity in your system.
I wouldn't worry about garbage collection - I would solve your problems using objects and autoboxing if you have to (or better yet, avoiding this "unknown set of input parameters" and get a solid protocol down). Once you have a working prototype, see if you run into performance problems, and then make necessary adjustments. You might find the JVM can handle those objects better than you originally thought.
Try to use the ... operator:
static int sum (int ... numbers)
{
int total = 0;
for (int i = 0; i < numbers.length; i++)
total += numbers [i];
return total;
}
You can use BitSet similar to C++ Bit field.
http://docs.oracle.com/javase/1.3/docs/api/java/util/BitSet.html
You could also cast all your primitives to double then just pass in an array of double. The only trick there is that you can't use the boolean type.
Fwiw, something like sum(int... numbers) would not autobox the ints. It would create a single int[] to hold them, so there would be an object allocation; but it wouldn't be per int.
public class VarArgs {
public static void main(String[] args) {
System.out.println(variableInts(1, 2));
System.out.println(variableIntegers(1, 2, 3));
}
private static String variableInts(int... args) {
// args is an int[], and ints can't have getClass(), so this doesn't compile
// args[0].getClass();
return args.getClass().toString() + " ";
}
private static String variableIntegers(Integer... args) {
// args is an Integer[], and Integers can have getClass()
args[0].getClass();
return args.getClass().toString();
}
}
output:
class [I
class [Ljava.lang.Integer;

Dynamically casting to primitives in Java

Edit: This has since been solved. Thanks to everyone who helped. Invoking the method after casting the object as the correct wrapper class worked. But String.valueOf() is much, much simpler to achieve the same effect.
Hello--
What I'm trying to do may not even be possible. I've spent a few hours now researching and experimenting with various things, so I figured I'd finally ask around to see if anyone knows if this is even possible.
Is it possible, using reflection, to dynamically cast a wrapper for a primitive of an unknown type as a primitive?
I'm basically trying to create a generic toString function which can handle the conversion of any type of primitive to a string. Such a seemingly simple thing is frustratingly difficult (and I am aware I could just test each type to see if it is of type Wrapper.class and cast it specifically, but at this point I'm just pursuing this out of stubbornness).
The following throws a ClassCastException. The primClass class appears to be the right one (gives "int" when printing primClass.getName()).
private String toString(Number obj){
String result = "";
try{
Class objClass = obj.getClass();
Field field = objClass.getDeclaredField("TYPE");
Class primClass = (Class)field.get(obj);
Method method = objClass.getMethod("toString", new Class[]{primClass});
Object args = new Object[]{primClass.cast(obj)};
result = (String)method.invoke(null, args);
}catch(Exception ex){
//Unknown exception. Send to handler.
handleException(ex);
}
return result;
}
So I'm a bit at a loss, really. Anyone have any ideas? Any help would be greatly appreciated.
Perhaps I'm missing something, but obj.toString() would do.
If you look at the implementations, it is calling String.valueOf(value) which in turn calls Double.toString(..) or Long.toString(..) or whatever. So, calling toString() automatically calls the required method. Without any reflection from your part.
You might want to have a look at Apache Commons Lang, Especially ToStringBuilder.reflectionToString(). Even if you don't want to introduce a dependency just for a toString(), it's open source so you can have a look at the implementation.
method.invoke accept the Wrapper types instead of the primivtes types.
Perhaps there is something I don't understand in your question but for primitive, you can do ""+primitive to cast it to a String.
What you are trying to do doesn't really make sense.... when your function is called with a primitive argument (e.g. an int) then it will automatically get boxed into an Integer. So you might as well just call obj.toString() on it.....
However if you really want to do something special with primitives, you might want to do something like the following using method overloading:
private String toString(Object obj){
return obj.toString();
}
private String toString(int intValue) {
// code to return string for the primitive int case, assuming it is different
}
// more overloads for other primitive argument types as needed.....
This can be a very useful technique for dealing with primitives in some cases.
The immediate problem in your code is that obj is an Object, and therefore cannot be an instance of a primitive type. (It must be an instance of the corresponding wrapper type). The primClass.cast(obj) call must fail for any primitive type class.
But if you simply want to turn a primitive wrapper instance to a String, just call the instance's toString() method.
String.valueOf(arg) will do it nicely too.

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