Validate return type of return method and parms in Java
I have a generic Callback object that provides a (primitive) callback capability for Java, in the absence of closures. The callback object contains the method and returns the parameters and return types for the method via a pair of accessors that simply delegate the equivalent methods in the method.
I am trying to verify that the callback I received points to a valid method. I need a number-compatible return type assignment and all parameters that need to be Double compatible. My validation method looks like this:
static public void checkFunctionSpec(Callback cbk) {
Class[] prms=cbk.getParmTypes();
Class ret =cbk.getReturnType();
if(!Number.class.isAssignableFrom(ret)) {
throw new IllegalArgumentException(
"A function callback must return a Number type " +
"(any Number object or numeric primitive) - function '" +
cbk + "' is not permitted");
}
for(Class prm: prms) {
if(!Double.class.isAssignableFrom(prm)) {
throw new IllegalArgumentException(
"A function callback must take parameters of " +
"assignment compatible with double " +
"(a Double or Float object or a double or float primitive) " +
"- function '" + cbk + "' is not permitted");
}
}
}
The problem I am running into is that when I try to do this, for example Math.abs (), it throws an exception for the return type like this:
java.lang.IllegalArgumentException:
A function callback must return a Number type (any Number object or numeric primitive)
- function 'public static double java.lang.Math.abs(double)' is not permitted
This was surprising to me, because I expected the primitives to just work, because (a) they are reflected using their wrapper classes and (b) Double.TYPE is declared to be of type Class <Double>.
Does anyone know how I can achieve this without changing my checks:
if(!Number.class.isAssignableFrom(ret)
&& ret!=Double.TYPE
&& ret!=Float.TYPE
&& ret!=...) {
Clarification
When you call a method double abs(double)
using the Method.invoke () method, you pass Object [] {Double} and return Double. However, my check fails because Double.TYPE is not assigned to Double. Since I need all of these callbacks to return some sort of number that will be returned by invoke () as a Number, I am trying to verify that the provided method returns either a Number or a numeric primitive.
Parma validation is also similar.
In other words, when using reflection, the types parm and return Double and double are identical, and I would like to easily justify them as such.
EDIT: To clarify: I want to confirm that the method will, when invoke () is called, return an object of type Number (from which I can call obj.doubleValue () to get the double that I want).
source to share
Looking more closely at the documentation for Class.isAssignableFrom (), it specifically states that the types for the primitive do not correspond to any class other than themselves. So I will need to specifically check for == equality of Byte.TYPE, Double.TYPE, Float.TYPE, Integer.TYPE, Long.TYPE and Short.TYPE for return type.
source to share
Why not do it with a compiler?
public interface F<A, B> {
public B $(A a);
}
Then you can pass to the F<Double, Double>
method that expects F<? extends Number, ? extends Number>
.
EDIT:
You say you want to provide one class for a function type with any number of arguments. This can be done using a Java type system. Conceptually, each function has only one argument. A function with two arguments is equivalent to a function that returns another function. So here's a variable whose value is a function that takes two doubles:
F<Double, F<Double, Double>> f;
Here's a method that skips two doubles for a given function:
public Double operate(F<Double, F<Double, Double>> f, double a, double b) {
return f.$(a).$(b);
}
Or consider a type L<A extends L>
with two subclasses C<E, T extends L<T>>
representing "minus" and a terminator type N
:
public abstract class L<A extends L<A>> {
private L() {}
private static final N nil = new N();
public static N nil() {
return nil;
}
public static final class N extends L<N> {
private N() {}
public <E> C<E, N> cons(final E e) {
return new C<E, L>(e, this);
}
}
public static final class C<E, L extends L<L>> extends L<C<E, L>> {
private E e;
private L l;
private C(final E e, final L l) {
this.e = e;
this.l = l;
}
public E head() {
return e;
}
public L tail() {
return l;
}
public <E> C<E, C<E, L>> cons(final E e) {
return new C<E, C<E, L>>(e, this);
}
}
}
In such a case, you can implement the function type:
public interface F<A extends L<A>, B> {
public B $(A args);
}
The following method expects a function with two arguments Double
(and returns a Double
) along with two Double
to apply it to:
public Double operate(F<C<Double, C<Double, N>>, Double> f, double a, double b) {
return f.$(N.nil().cons(b).cons(a));
}
The interface implementation F
would have to get the arguments from the list using head
and tail
. This way you are implementing LISP in Java. :)
Having said that, check out Functional Java , which is already a library that already has a lot of this in it. I'm sure there is also one out there that uses reflection, so you don't have to write it yourself.
source to share
The Math.abs () parameter is a double primitive. I'm not really sure what you mean by primitive, "assignment-compatible" with an object (which essentially means the reflection API, "might be great"). But if you mean "can go to a double constructor", then this is essentially a primitive double (or string) !! Perhaps you need to clarify a little more, what do you need to do?
source to share