代码之家  ›  专栏  ›  技术社区  ›  L. Cornelius Dol

验证Java中反射的方法返回类型和参数

  •  0
  • L. Cornelius Dol  · 技术社区  · 17 年前

    我有一个通用回调对象,它在没有闭包的情况下为Java提供(基本的)回调功能。回调对象包含一个方法,并通过两个访问器方法返回该方法的参数和返回类型,这些方法只是委托给方法中的等效方法。

    我试图验证提供给我的回调是否指向有效的方法。我需要返回类型赋值与Number兼容,所有参数赋值与Double兼容。我的验证方法如下所示:

    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");
                }
            }
        }
    

    我遇到的问题是,当我尝试使用Math.abs()时,它会为返回类型抛出一个异常,如下所示:

    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
    

    有人知道我如何在不修改支票的情况下实现这一点吗

    if(!Number.class.isAssignableFrom(ret)
         && ret!=Double.TYPE
         && ret!=Float.TYPE
         && ret!=...) {
    

    澄清

    当您调用该方法时 double abs(double) 使用Method.invoke(),传入一个对象[]{Double},然后返回一个Double。但是,我的验证似乎失败了,因为Double.TYPE不可分配给Double。由于我要求所有这些回调都返回某种数字,invoke()会将其作为数字返回,因此我尝试验证提供的方法是否返回数字或数字原语。

    parms的验证也是如此。

    换句话说,当使用反射时,parm和返回类型Double和Double是相同的,我想验证它们 容易地 像这样的

    编辑:为了进一步澄清:我想验证当调用invoke()时,方法是否会返回一个Number类型的对象(从中我可以调用obj.doubleValue()来获得我想要的double)。

    3 回复  |  直到 17 年前
        1
  •  1
  •   L. Cornelius Dol    17 年前

    更仔细地查看Class.isAssignableFrom()的文档,它特别指出基元的类型与除自身之外的任何类都不匹配。因此,我需要专门检查返回类型的==是否等于Byte.TYPE、Double.TYPE、Float.TYPE、Integer.TYPE、Long.TYPE和Short.TYPE。

        2
  •  1
  •   Apocalisp    17 年前

    为什么不让编译器来做呢?

    public interface F<A, B> {
       public B $(A a);
    }
    

    F<Double, Double> F<? extends Number, ? extends Number>

    编辑:

    可以 可以使用Java类型系统完成。从概念上讲,每个函数只有一个参数。具有两个参数的函数等价于返回另一个函数的函数。这是一个变量,它的值是一个取两个双精度的函数:

    F<Double, F<Double, Double>> f;
    

    下面是一个将两个double传递给给定函数的方法:

    public Double operate(F<Double, F<Double, Double>> f, double a, double b) {
       return f.$(a).$(b);
    }
    

    L<A extends L> 有两个子类 C<E, T extends L<T>> 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);
       }  
     }  
    
    }  
    

    在这种情况下,您可以实现一个函数类型:

    public interface F<A extends L<A>, B> {
       public B $(A args);
    }
    

    Double 参数(并返回 双重的 double s将其应用于:

    public Double operate(F<C<Double, C<Double, N>>, Double> f, double a, double b) {
       return f.$(N.nil().cons(b).cons(a));
    }
    

    实施 F 接口必须使用 head tail . 实际上,您正在用Java实现LISP

    话虽如此,请查收 Functional Java ,这是一个已经有很多这种东西的图书馆。我相信也有一种是使用反射的,这样你就不用自己写了。

        3
  •  0
  •   Neil Coffey    17 年前