Frage

Dies kann etwas gemeinsam und trivial sein, aber ich scheinen Schwierigkeiten zu haben, eine konkrete Antwort zu finden. In C # gibt es ein Konzept der Delegierten, die sich stark auf die Idee der Funktionszeiger von C ++ bezieht. Gibt es eine ähnliche Funktionalität in Java? Da die Zeiger etwas fehlen, was ist der beste Weg, um dies? Und klar zu sein, wir reden erste Klasse hier.

War es hilfreich?

Lösung

Das Java-Idiom für Funktionszeiger-ähnliche Funktionalität ist eine anonyme Klasse eine Schnittstelle implementiert, z.

Collections.sort(list, new Comparator<MyClass>(){
    public int compare(MyClass a, MyClass b)
    {
        // compare objects
    }
});

Update: die oben in Java-Versionen notwendig ist, vor dem Java 8. Jetzt haben wir viel schöner Alternativen, nämlich Lambda-Ausdrücke:

list.sort((a, b) -> a.isGreaterThan(b));

und Verfahren Referenzen:

list.sort(MyClass::isGreaterThan);

Andere Tipps

Sie können einen Funktionszeiger mit einer Schnittstelle substitue. Sagen wir Sie durch eine Sammlung ausgeführt werden soll und etwas tun, mit jedem Element.

public interface IFunction {
  public void execute(Object o);
}

Dies ist die Schnittstelle wir einige sagen CollectionUtils2.doFunc (Sammlung c, iFunction f).

passieren könnte
public static void doFunc(Collection c, IFunction f) {
   for (Object o : c) {
      f.execute(o);
   }
}

Als Beispiel sagen wir eine Sammlung von Zahlen haben, und Sie möchten 1 zu jedem Element hinzuzufügen.

CollectionUtils2.doFunc(List numbers, new IFunction() {
    public void execute(Object o) {
       Integer anInt = (Integer) o;
       anInt++;
    }
});

Sie können mit Reflexion tun.

Geben als Parameter das Objekt und den Methodennamen (als eine Zeichenfolge) und dann die Methode aufzurufen. Zum Beispiel:

Object methodCaller(Object theObject, String methodName) {
   return theObject.getClass().getMethod(methodName).invoke(theObject);
   // Catch the exceptions
}

Und dann verwenden, wie in:

String theDescription = methodCaller(object1, "toString");
Class theClass = methodCaller(object2, "getClass");

Natürlich alle Ausnahmen überprüfen und die erforderlichen Abgüsse hinzufügen.

Nein, Funktionen sind nicht erstklassige Objekte in Java. Sie können durch die Implementierung eines Handler-Klasse das gleiche tun -. Das ist, wie Rückrufe in Swing implementiert etc

Es gibt jedoch Vorschläge für Verschlüsse (der offizielle Name für das, was Sie sprechen) in zukünftigen Versionen von Java - Javaworld hat einen interessanten Artikel.

Das bringt Steve Yegge Ausführung kümmern in das Königreich Substantive . Darin heißt es im Grunde, dass Java ein Objekt für jede Aktion muss und daher nicht „Verb-only“ Entitäten wie Funktionszeiger hat.

ähnliche Funktionalität erreichen Sie anonyme innere Klassen verwenden könnten.

Wenn Sie sind eine Schnittstelle Foo definieren:

interface Foo {
    Object myFunc(Object arg);
}

Erstellen Sie eine Methode bar, die einen "Funktionszeiger als Argument erhalten:

public void bar(Foo foo) {
    // .....
    Object object = foo.myFunc(argValue);
    // .....
}

Schließlich rufen Sie die Methode wie folgt:

bar(new Foo() {
    public Object myFunc(Object arg) {
        // Function code.
    }
}

Java8 eingeführt lambdas und Methode Referenzen . Also, wenn Ihre Funktion entspricht ein funktionale Schnittstelle ( Sie können Ihre eigene erstellen) eine Methode Referenz in diesem Fall verwendet werden kann.

Java bietet eine Reihe von funktionale Schnittstellen . während Sie tun das auch folgendes:

public class Test {
   public void test1(Integer i) {}
   public void test2(Integer i) {}
   public void consumer(Consumer<Integer> a) {
     a.accept(10);
   }
   public void provideConsumer() {
     consumer(this::test1);   // method reference
     consumer(x -> test2(x)); // lambda
   }
}

Es gibt nicht so etwas in Java. Sie müssen Ihre Funktion in ein Objekt wickeln und die Referenz auf das Objekt, um den Verweis auf die Methode übergeben an diesem Objekt zu übergeben.

syntaktisch, kann dies als Membervariablen der Klasse definiert an Ort und Stelle oder anonyme Klassen definiert unter Verwendung von anonymen Klassen in einem gewissen Ausmaß gelockert werden.

Beispiel:

class MyComponent extends JPanel {
    private JButton button;
    public MyComponent() {
        button = new JButton("click me");
        button.addActionListener(buttonAction);
        add(button);
    }

    private ActionListener buttonAction = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            // handle the event...
            // note how the handler instance can access 
            // members of the surrounding class
            button.setText("you clicked me");
        }
    }
}

Ich habe Rückruf implementiert / delegieren Unterstützung in Java unter Verwendung von Reflexion. Details und Arbeits Quelle sind auf meiner Website .

Wie es funktioniert

Wir haben ein Prinzip Klasse mit dem Namen Callback mit einem verschachtelten Klasse mit dem Namen WithParms. Die API, die den Rückruf muss ein Rückrufobjekt als Parameter nehmen und, falls notwendig, eine Callback.WithParms als Methode variable erstellen. Da ein großer Teil der Anwendungen dieses Objekt rekursiv sein wird, das funktioniert sehr sauber.

Mit Leistung noch eine hohe Priorität für mich, ich wollte nicht erforderlich sein, um einen Wegwerf-Objekt-Array zu erstellen, die Parameter für jeden Aufruf zu halten - schließlich in einer großen Datenstruktur gibt es Tausende von Elementen sein könnte, und in ein Nachrichtenverarbeitungsszenario könnten wir tausende von Datenstrukturen Verarbeitung ein zweites Ende.

sein, um der Parameterthread Array für jeden Aufruf der API-Methode eindeutig vorhanden sein muss, und für die Effizienz des gleiche soll für jeden Aufruf des Rückrufs verwendet werden; I benötigen ein zweites Objekt, das wäre billig zu schaffen, um den Rückruf mit einem Parameter-Array für den Aufruf zu binden. Aber in einigen Szenarien würden die Aufrufer haben bereits einen der Parameter-Array aus anderen Gründen. Aus diesen beiden Gründen gehörte der Parameter-Array in dem Callback-Objekt nicht. Auch die Wahl des Aufrufs (vorbei an die Parameter als ein Array oder als einzelne Objekte) gehört in den Händen der API den Rückruf mit ermöglicht, es zu benutzen Unabhängig davon, welche Aufruf ist am besten geeignet, um es Innenleben.

Die WithParms geschachtelte Klasse, ist, optional und dient zwei Zwecken, ist es die Parameter Objektarray für den Rückruf Invokationen benötigt enthält, und es bietet 10 überlastet Invoke () Verfahren (mit 1 bis 10 Parameter), das Laden der Parameter Array und dann die Callback-Ziel aufrufen.

die Verschlüsse prüfen, wie sie in der lambdaj Bibliothek umgesetzt wurden. Sie haben tatsächlich ein Verhalten sehr ähnlich zu C # Delegierten:

http://code.google.com/p/lambdaj/wiki/Closures

Im Vergleich zu den meisten Menschen hier Ich bin neu in Java, aber da ich nicht einen ähnlichen Vorschlag gesehen habe ich habe eine andere Alternative vorzuschlagen. Wenn es im nicht sicher, eine gute Praxis, oder nicht, oder sogar vorgeschlagen, vor und ich habe es einfach nicht. Ich mag es einfach, da ich seinen selbsterklärend denken.

 /*Just to merge functions in a common name*/
 public class CustomFunction{ 
 public CustomFunction(){}
 }

 /*Actual functions*/
 public class Function1 extends CustomFunction{
 public Function1(){}
 public void execute(){...something here...}
 }

 public class Function2 extends CustomFunction{
 public Function2(){}
 public void execute(){...something here...}
 }

 .....
 /*in Main class*/
 CustomFunction functionpointer = null;

dann je nach Anwendung zuweisen

 functionpointer = new Function1();
 functionpointer = new Function2();

usw.

und rufen Sie mit

 functionpointer.execute();
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top