Frage

Ich habe ein generisches Callback-Objekt, das für Java, in Abwesenheit von Schließungen eine (primitive) Callback-Fähigkeit zur Verfügung stellt. Das Callback-Objekt enthält eine Methode, und gibt die Parameter und Rückgabetypen für das Verfahren über ein Paar von Zugriffsmethoden, die nur auf die äquivalenten Verfahren in Methode delegieren.

Ich versuche, zu bestätigen, dass ein Rückruf Ich habe auf ein gültiges Verfahren geliefert. Ich brauche die Typzuweisung Rückkehr kompatibel mit Nummer und alle Parameter Zuordnung kompatibel mit Doppel sein. Meine Validierung Methode sieht wie folgt aus:

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

Das Problem, das ich ist begegnen, dass die bei dem Versuch, dies mit z.B. Math.abs (), es ist eine Ausnahme für den Rückgabetyp wirft wie folgt:

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

Das war für mich überraschend, weil ich Primitive erwartete einfach zu arbeiten, weil (a) sie ihre Wrapper-Klassen mit reflektiert werden, und (b) der Double.TYPE deklariert ist vom Typ seines Klasse .

Wer weiß, wie ich das erreichen kann meine Schecks ohne Änderung zu sein:

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

Klarstellung

Wenn Sie die Methode double abs(double) mit Method.invoke () aufrufen, übergeben Sie in einem Object [] {} Doppel und einen Doppel zurück. Allerdings scheint meine Prüfung fehlschlägt, weil Double.TYPE nicht übertragbar auf ein Double ist. Da ich all diese Rückrufe erfordern eine Art von Zahl zurück, die von invoke zurückgegeben wird () als Zahl, versuche ich zu bestätigen, dass das gelieferte Verfahren entweder Zahl oder ein numerischer primitive zurück.

Die Validierung der parms ebenfalls.

Mit anderen Worten, wenn Reflexion mit dem Parm und Rückgabetypen Doppel- und Doppel sind identisch, und ich mag sie validieren leicht als solche.

EDIT: Um zu klären. Ich überprüfen möchten, dass eine Methode, bei der invoke () return ein Objekt vom Typ Nummer aufgerufen wird (von dem ich obj.doubleValue () aufrufen können, um das doppelte zu bekommen ich will)

War es hilfreich?

Lösung

Bei genauerer Betrachtung der Dokumentation Class.isAssignableFrom () heißt es ausdrücklich, dass die Typen für ein primitiv Sie jede Klasse nicht nur mich selbst entsprechen. So muss ich speziell für == Gleichheit Byte.TYPE, Double.TYPE, Float.TYPE, Integer.TYPE, Long.TYPE und Short.TYPE für den Rückgabetyp überprüfen.

Andere Tipps

Warum nicht die Compiler hat es tun?

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

Dann können Sie eine F<Double, Double> an eine Methode übergeben, die eine F<? extends Number, ? extends Number> erwartet.

EDIT:

Sie sagen, Sie eine einzige Klasse für den Typ einer Funktion mit einer beliebigen Anzahl von Argumenten zur Verfügung stellen möchten. Diese können mit dem Java-Typ-System durchgeführt werden. Konzeptionell hat jede Funktion nur ein Argument. Eine Funktion mit zwei Argumenten entspricht einer Funktion, die eine andere Funktion zurückgibt. Also hier ist eine Variable, deren Wert eine Funktion, die zwei Doppelzimmer nimmt:

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

Hier ist eine Methode, die zwei Doppelzimmer zu einer bestimmten Funktion übergibt:

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

Oder betrachten eine Art L<A extends L> mit zwei Unterklassen C<E, T extends L<T>> die eine „cons“ und ein Terminator Typ 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 einem solchen Fall können Sie einen Funktionstyp implementieren thusly:

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

Die folgende Methode erwartet eine Funktion mit zwei Argumenten Double (und gibt ein Double), zusammen mit zwei doubles es gilt für:

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

Die Umsetzung der F Schnittstelle müßte die Argumente aus der Liste bekommen mit head und tail. Also in der Tat, sind Sie LISP in Java implementiert. :)

Having said that Besuche Functional Java , die eine Bibliothek, die eine Menge von diesem Zeug schon hat. Ich bin sicher, es gibt auch eine gibt, die Reflexion verwendet, so dass Sie nicht, es selbst zu schreiben haben.

Der Parameter Math.abs () ist die Doppel primitiv. Ich bin mir nicht ganz sicher, was Sie von einer primitiven Wesen „Zuordnung kompatibel“ bedeuten, mit einem Objekt (was der Reflection-API im Wesentlichen bedeutet, ist „kann eine Besetzung von sein“). Aber wenn du meinst „in einen Doppel Konstruktor übergeben kann“, dann ist das im Wesentlichen eine primitive Doppel (oder eine Zeichenkette) !! Vielleicht brauchen Sie ein bisschen mehr zu klären, was Sie tun müssen?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top