Dies mag etwas Alltägliches und Triviales sein, aber ich scheine Schwierigkeiten zu haben, eine konkrete Antwort zu finden. In C# gibt es ein Konzept von Delegaten, das sich stark an die Idee von Funktionszeigern aus C++ anlehnt. Gibt es eine ähnliche Funktionalität in Java? Angesichts der Tatsache, dass Hinweise etwas fehlen, was ist der beste Weg, dies zu tun? Und um das klarzustellen, wir reden hier erstklassig.
Funktionszeiger in Java
Michael Borgwart
Das Java-Idiom für funktionszeigerähnliche Funktionalität ist eine anonyme Klasse, die eine Schnittstelle implementiert, z
Collections.sort(list, new Comparator<MyClass>(){
public int compare(MyClass a, MyClass b)
{
// compare objects
}
});
Aktualisieren: Das Obige ist in Java-Versionen vor Java 8 erforderlich. Jetzt haben wir viel schönere Alternativen, nämlich Lambdas:
list.sort((a, b) -> a.isGreaterThan(b));
und Methodenreferenzen:
list.sort(MyClass::isGreaterThan);
-
@Raedwald C++ hat Funktoren und C++0x hat Closures und Lambdas, die auf Funktoren aufbauen. Das hat es sogar
std::bind
, die Parameter an Funktionen bindet und ein aufrufbares Objekt zurückgibt. Ich kann C aus diesen Gründen nicht verteidigen, aber C++ wirklich ist besser als Java dafür.– zneak
2. März 11 um 4:48 Uhr
-
@zneak, @Raedwald: Sie können dies in C tun, indem Sie einen Zeiger auf Benutzerdaten übergeben (zB: struct). (und kann es mit jeder neuen Callback-Indirektion kapseln) Es ist eigentlich ziemlich sauber.
– Briese
10. Juni 11 um 14:06 Uhr
-
Ja, ich werde tatsächlich jeden Tag Crufty-Funktionszeiger über Crufty-Wrapper-Klassen nehmen
– BT
17. Mai ’12 um 2:26 Uhr
-
@Raedwald, dafür sind Delegierte in C# da! Sie sind saubere, typsichere Funktionszeiger.
– devinbost
9. Mai 14 um 6:51 Uhr
-
Java 8 hat dafür eine bessere Syntax.
– Thorbjørn Ravn Andersen
25. Juni 14 um 9:42 Uhr
raupach
Sie können einen Funktionszeiger durch eine Schnittstelle ersetzen. Angenommen, Sie möchten eine Sammlung durchlaufen und mit jedem Element etwas tun.
public interface IFunction {
public void execute(Object o);
}
Dies ist die Schnittstelle, die wir beispielsweise an CollectionUtils2.doFunc(Collection c, IFunction f) übergeben könnten.
public static void doFunc(Collection c, IFunction f) {
for (Object o : c) {
f.execute(o);
}
}
Als Beispiel sagen wir, wir haben eine Sammlung von Zahlen und Sie möchten zu jedem Element 1 hinzufügen.
CollectionUtils2.doFunc(List numbers, new IFunction() {
public void execute(Object o) {
Integer anInt = (Integer) o;
anInt++;
}
});
zoquete
Sie können die Reflexion dazu verwenden.
Übergeben Sie als Parameter das Objekt und den Methodennamen (als Zeichenfolge) und rufen Sie dann die Methode auf. Beispielsweise:
Object methodCaller(Object theObject, String methodName) {
return theObject.getClass().getMethod(methodName).invoke(theObject);
// Catch the exceptions
}
Und dann verwenden Sie es wie in:
String theDescription = methodCaller(object1, "toString");
Class theClass = methodCaller(object2, "getClass");
Überprüfen Sie natürlich alle Ausnahmen und fügen Sie die erforderlichen Umwandlungen hinzu.
-
Reflexion ist nicht die richtige Antwort auf irgendetwas außer “Wie schreibe ich langsamen zwielichtigen Java-Code” 😀
– Jay
5. August 13 um 12:34 Uhr
-
Es mag “hässlich” und langsam sein, aber ich glaube, dass die Reflexion es ermöglicht, Dinge zu tun, die die schnittstellenbasierte Lösung in der akzeptierten Antwort nicht kann (es sei denn, ich irre mich), nämlich verschiedene Methoden desselben Objekts innerhalb desselben Codes aufzurufen Portion.
– Eusebius
9. April 14 um 6:50 Uhr
-
@zoquete.. Ich habe diesen Beitrag durchgesehen und hatte Zweifel.. Wenn ich also in Ihrem Ansatz auf die Variable “theDescription” zugreife, wird die Funktion jedes Mal aufgerufen, wenn auf die Variable zugegriffen wird.
– karthik27
16. April 14 um 18:48 Uhr
jwoolard
Nein, Funktionen sind keine erstklassigen Objekte in Java. Sie können dasselbe tun, indem Sie eine Handler-Klasse implementieren – so werden Callbacks in Swing usw. implementiert.
Es gibt jedoch Vorschläge für Schließungen (der offizielle Name für das, worüber Sie sprechen) in zukünftigen Versionen von Java – Javawelt hat einen interessanten Artikel.
Das erinnert an Steve Yegges Hinrichtung im Reich der Substantive. Es besagt im Grunde, dass Java für jede Aktion ein Objekt benötigt und daher keine „Nur-Verb“-Entitäten wie Funktionszeiger hat.
Um eine ähnliche Funktionalität zu erreichen, könnten Sie anonyme innere Klassen verwenden.
Wenn Sie eine Schnittstelle definieren würden Foo
:
interface Foo {
Object myFunc(Object arg);
}
Erstellen Sie eine Methode bar
die einen ‘Funktionszeiger’ als Argument erhält:
public void bar(Foo foo) {
// .....
Object object = foo.myFunc(argValue);
// .....
}
Rufen Sie die Methode schließlich wie folgt auf:
bar(new Foo() {
public Object myFunc(Object arg) {
// Function code.
}
}
Alexander Ach
Java8 hat Lambdas und eingeführt Methodenreferenzen. Wenn Ihre Funktion also mit a übereinstimmt funktionale Schnittstelle (Sie können Ihre eigene erstellen) Sie können in diesem Fall eine Methodenreferenz verwenden.
Java bietet eine Reihe von gemeinsame Funktionsschnittstellen. während Sie Folgendes tun könnten:
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
}
}
-
gibt es das Konzept eines
alias
: z.Bpublic List<T> collect(T t) = Collections::collect
– WestCoastProjects
5. Januar 20 um 19:50 Uhr
-
@javadba soweit ich weiß nicht.
– Alexander Ach
5. Januar 20 um 20:57 Uhr
.
Ich bin nur neugierig, warum Sie dies wollen, wo Listener oder andere OOP-Konstrukte die gleiche Aufgabe erledigen würden, während sie ihre Objektnatur beibehalten. Ich meine, ich verstehe die Notwendigkeit der Funktionalität, die das Konzept bietet, nur dass sie mit einem einfachen Objekt erreicht werden kann. Es sei denn, mir fehlt natürlich etwas, daher meine Frage! 🙂
– Neutopisch
2. Juli 09 um 10:58 Uhr
Java 8 hat Lambda-Ausdrücke: docs.oracle.com/javase/tutorial/java/javaOO/… Vielleicht möchten Sie das überprüfen. Nicht ganz ein Funktionszeiger, aber vielleicht noch nützlicher.
– FrustriertMitFormularDesigner
6. Mai 14 um 19:51 Uhr
Java 8-Methodenreferenzen sind genau das, wonach Sie fragen.
– Stefan
5. Juni 14 um 08:23 Uhr
Java 8 Methodenreferenzen ist genau das, wonach Sie fragen.
this::myMethod
ist semantisch dasselbe wie das Erstellen eines LambdaparamA, paramB -> this.myMethod(paramA, paramB)
.– Stefan
5. Juni 14 um 8:30 Uhr
mögliches Duplikat von Was ist der nächste Ersatz für einen Funktionszeiger in Java?
– nawfal
5. Juli 14 um 7:19 Uhr