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).

0


source to share


3 answers


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.



+1


source


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.

+1


source


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?

0


source







All Articles