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.
Related
In Java, a method could be defined as following:
Object m(boolean b) {
if (b) {
return "123";
} else {
return new Integer(123);
}
}
In this case, the return value of m could be either String or Integer in runtime. So is there any way to get all possible run time return types of a method in static time?
For this particular method, yes. Just call it with true and false and check the return value with getClass(). For a general case, no.
Generally you wouldn't need to either. Thanks to Java's strong typing and generics, the type of the return value should never be a huge surprise.
Returning multiple different types as shown in your example should be avoided, and in cases where it's useful/necessary (such as factory pattern) it should be irrelevant to the caller.
If you know the implementation of the method, yes. You know all the types it could return because you can read the code and tell for yourself what they are.
But, programmatically? For any method, in general? No, you can't do that, not at run-time. This is why it's very important to write good, sensical method signatures with meaningful return-types. Returning Object is seldom the best idea. When you say that your method returns Object, the contract of that method is that literally anything is allowed to come out of it. There's nothing wrong with that, but that's the most specific thing you can say about a method if all you know is its signature.
I thought only functions had return statements since they were explicitly called whereas methods are implicitly called on the class. However, I have seen examples of code where a method has a return statement. Is this conventional? Also, am I wrong in saying that only functions return values, and are methods having return statements a standard convention across multiple languages of only OOP languages?
A method is a function that is associated with an object (or class). So yes, they can return values, or not.
Also - trying things out yourself and/or reading documentation is a much better way to learn than asking us as soon as you get stuck! ;)
Here is Oracle's documentation for defining methods.
I think this is problems of theory. Let me put clear some points.
Before OOP
procedures was a bits of programs for do someting
functions was a bits of programs for do someting and return values, like Math f(x) = x*y+E2
After OOP
procedures and functions are called methods and is equal if they return or not some value.
PD: Also we have methods:
with firm: function A(b,x) { ... }
without firm: function A() { ... }
anoimate: function () { ... }
The post contains incorrect assumptions. For starters Java only has "methods (in this context), even if static. Given this it is trivially true that methods at large in Java can return a value.
Now, as an example1, for an equivalency with a language like VB.NET (which derives from BASIC),
A method that returns a value is a "Function Procedure" (BASIC lingo) - these methods return a value and can then be used as an appropriately-typed expression. They must contain a return statement on all possible code-execution paths.
A method that has a void return type is a "Sub Procedure" (BASIC lingo) - these methods do not (and cannot) return a value. Such methods may only be called as statements.
1 The terms "function", "procedure", and "subroutine", eg, are highly dependent upon language/context which is why the above is prefaced. As such, correct Java-terminology dictates using "methods [returning some value upon completion]" and "void methods" to describe the difference - although I find that "function" is still used colloquially (in my circles) when describing the operation of "computing a value without side effects" or when such is supplied as a higher-order argument (eg. lambdas).
Methods can have return statements as long as the return type is not void. When you define the method, you can make the method public or private, static or not static, choose the return type (byte, short, int, long, float, double, boolean, char), name the method, and define the inputs.
`public static returnType methodName(input) {
// body
}`
Is it a bad practice to pass NULL argument to methods or in other words should we have method definitions which allow NULL argument as valid argument.
Suppose i want two method
1. to retrieve list of all of companies
2. to retrieve list of companies based upon filter.
We can either have two methods like as below
List<Company> getAllCompaniesList();
List<Company> getCompaniesList(Company companyFilter);
or we can have one single method
List<Company> getCompaniesList(Company companyFilter);
here in second case, if argument is NULL then method return list of all of companies.
Beside question of good practice practically i see one more issue with later approach which is explained below.
I am implementing Spring AOP, in which i want to have some checks on arguments like
1. Is argument NULL ?
2. is size of collection 0?
There are some scenarios where we can not have null argument at all like for method
void addBranches(int companyId, List<Branch>);
This check can be performed very well by using Spring AOP by defining method like following
#Before(argNames="args", value="execution(* *)")
void beforeCall(JoinPoint joinPoint ,Object[] args )
{
foreach(Object obj in args)
{
if(obj == NULL)
{
throw new Exception("Argument NULL");
}
}
}
But problem i am facing is since i have defined some of methods which should accept NULL argument for multiple functionality of one single method as mentioned above for method List getCompaniesList(Company companyFilter);
So i can not apply AOP uniformly for all of methods and neither some expression for methods name match will be useful here.
Please let me know if more information is required or problem is not descriptive enough.
Thanks for reading my problem and giving thought upon it.
It's fine, in cases when there are too many overloaded methods. So instead of having all combinations of parameters, you allow some of them to be null. But if you do so, document this explicitly with
#param foo foo description. Can be null
In your case I'd have the two methods, where the first one invokes the second with a null argument. It makes the API more usable.
There is no strict line where to stop overloading and where to start relying on nullable parameters. It's a matter of preference. But note that thus your method with the most params will allow some of them to be nullable, so document this as well.
Also note that a preferred way to cope with multiple constructor parameters is via a Builder. So instead of:
public Foo(String bar, String baz, int fooo, double barr, String asd);
where each of the arguments is optional, you can have:
Foo foo = new FooBuilder().setBar(bar).setFooo(fooo).build();
I use a very simple rule:
Never allow null as an argument or return value on a public method.
I make use of Optional and Preconditions or AOP to enforce that rule.
This decision already saved me tons of hours bugfixing after NPE's or strange behaviour.
It's common practice, but there are ways of making your code clearer - avoiding null checks in sometimes, or moving them elsewhere. Look up the null object pattern - it may well be exactly what you need: http://en.m.wikipedia.org/wiki/Null_Object_pattern?wasRedirected=true
The rule is: simple interface, complicated implementation.
Design decisions about your API should be made by considering how the client code is likely to use it. If you expect to see either
getAllCompaniesList(null);
or
if (companyFilter == null) {
getAllCompaniesList();
} else {
getAllCompaniesList(companyFilter);
}
then you're doing it wrong. If the likely use-case is that the client code will, at the time it is written, either have or not have a filter, you should supply two entry points; if that decision is likely not made until run-time, allow a null argument.
Another approach that may be workable may be to have a CompanyFilter interface with an companyIsIncluded(Company) method that accepts a Company and returns true or false to say whether any company should be included. Company could implement the interface so that companyIsIncluded method's behavior mirrored equals(), but one could easily have a singleton CompanyFilter.AllCompanies whose companyIsIncluded() method would always return true. Using that approach, there's no need to pass a null value--just pass a reference to the AllComapnies singleton.
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.
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?