Wie übergebe ich eine Funktion als Parameter in Java? [duplicate]

Lesezeit: 9 Minuten

Wie ubergebe ich eine Funktion als Parameter in Java duplicate
Jason

Wie kann man in Java eine Funktion als Argument einer anderen Funktion übergeben?

  • stackoverflow.com/questions/4685435/…

    – Kratylus

    13. Januar 2011 um 21:40 Uhr

  • Sie können ein Objekt übergeben, für das Sie eine Methode definiert haben, die Sie als Parameter verwenden möchten

    – Sternkorn

    13. Januar 2011 um 22:01 Uhr


  • Weitere Antworten zur Verwendung einer Lambda-Funktion oder zur Übergabe als Parameter: einfacher Beispielparameter als Funktion java.

    – Sylhare

    9. November 2018 um 4:41 Uhr

1646312231 797 Wie ubergebe ich eine Funktion als Parameter in Java duplicate
jk.

Java 8 und höher

Verwenden Sie Java 8+ Lambda-Ausdrücke, wenn Sie eine Klasse oder Schnittstelle mit nur einer einzigen abstrakten Methode (manchmal auch als SAM-Typ bezeichnet) haben, zum Beispiel:

public interface MyInterface {
    String doSomething(int param1, String param2);
}

dann können Sie überall dort, wo MyInterface verwendet wird, einen Lambda-Ausdruck ersetzen:

class MyClass {
    public MyInterface myInterface = (p1, p2) -> { return p2 + p1; };
}

Sie können zum Beispiel sehr schnell einen neuen Thread erstellen:

new Thread(() -> someMethod()).start();

Und benutze die Methodenreferenzsyntax um es noch sauberer zu machen:

new Thread(this::someMethod).start();

Ohne Lambda-Ausdrücke, diese letzten beiden Beispiele würden so aussehen:

new Thread(new Runnable() { someMethod(); }).start();

Vor Java 8

Ein gängiges Muster wäre es, es innerhalb einer Schnittstelle zu “verpacken”, wie z Callabledann übergeben Sie beispielsweise ein Callable:

public T myMethod(Callable<T> func) {
    return func.call();
}

Dieses Muster ist als bekannt Befehlsmuster.

Denken Sie daran, dass Sie am besten eine Schnittstelle für Ihre spezielle Verwendung erstellen. Wenn Sie sich für Callable entschieden haben, ersetzen Sie T oben durch einen beliebigen Typ von Rückgabewert, den Sie erwarten, z. B. String.

Als Antwort auf Ihren Kommentar unten könnten Sie sagen:

public int methodToPass() { 
        // do something
}

public void dansMethod(int i, Callable<Integer> myFunc) {
       // do something
}

Rufen Sie es dann auf, vielleicht mit einer anonymen inneren Klasse:

dansMethod(100, new Callable<Integer>() {
   public Integer call() {
        return methodToPass();
   }
});

Denken Sie daran, dass dies kein „Trick“ ist. Es ist nur Javas grundlegendes konzeptionelles Äquivalent zu Funktionszeigern.

  • Können Sie zeigen, was genau an Folgendes übergeben würde: public void DansMethod(int i, ){ }

    – Jason

    13. Januar 2011 um 21:43 Uhr

  • Ich bräuchte eine viel einfachere Lösung. Kann jemand helfen?

    – TomeenNS

    3. Januar 2014 um 0:27 Uhr

  • Für die über 100 Methoden, für die ich dies tun muss, benötige ich also über 100 Schnittstellen. ggreattttt =/

    – Alexander

    22. Mai 2014 um 23:05 Uhr

  • @XAleXOwnZX Sie könnten eine einzige Callable<>-Schnittstelle verwenden, aber Sie müssten mehr als 100 anonyme innere Klassen vom Typ Callable<> erstellen. Natürlich können Sie jetzt Java 8-Lambda-Ausdrücke verwenden, um dies zu vereinfachen, was zum Zeitpunkt des Schreibens dieser Antwort noch nicht verfügbar war.

    – jk.

    24. Mai 2014 um 19:19 Uhr

  • @TomeeNS – hier ist ein einfaches Beispiel, bei dem foo() die als Parameter übergebene Funktion ist und demo() die Funktion ist, die eine Funktion als Parameter übernimmt. Void-Demo (final Callable func) { func.call(); } Void foo () { Null zurückgeben; } demo(new Callable() {public Void call() {return foo();}}

    – Videospielboy76

    23. Oktober 2014 um 20:19 Uhr


Wie ubergebe ich eine Funktion als Parameter in Java duplicate
bteig

Dazu können Sie Java Reflection verwenden. Die Methode würde als Instanz von dargestellt werden java.lang.reflect.Method.

import java.lang.reflect.Method;

public class Demo {

    public static void main(String[] args) throws Exception{
        Class[] parameterTypes = new Class[1];
        parameterTypes[0] = String.class;
        Method method1 = Demo.class.getMethod("method1", parameterTypes);

        Demo demo = new Demo();
        demo.method2(demo, method1, "Hello World");
    }

    public void method1(String message) {
        System.out.println(message);
    }

    public void method2(Object object, Method method, String message) throws Exception {
        Object[] parameters = new Object[1];
        parameters[0] = message;
        method.invoke(object, parameters);
    }

}

  • @Tim Bender: oder vielleicht im “Spiegel”?

    – Sowa

    13. Januar 2011 um 21:45 Uhr

  • Ah, Java-Eigenheiten … Was würden wir ohne sie tun?

    – SyntaxT3rr0r

    13. Januar 2011 um 23:21 Uhr

  • Was ist, wenn Ihre Funktion keine Parameter hat und nichts zurückgibt?

    – Alleine im Dunkeln

    14. März 2014 um 10:07 Uhr

  • @AloneInTheDark: Wenn du es dir ansiehst die Dokumentation Sie werden feststellen, dass die Argumente zu invoke sind optional. Ebenfalls, void Methoden zurück null. __P.S. Und für deinen speziellen Fall: Vorgeschlagene Literatur.

    – Daniel

    20. April 2015 um 17:48 Uhr

1646312232 330 Wie ubergebe ich eine Funktion als Parameter in Java duplicate
Der Typ mit dem Hut

Lambda-Ausdrücke

Um die hervorragende Antwort von jk. zu ergänzen, können Sie jetzt eine Methode einfacher weitergeben Lambda-Ausdrücke (unter Java 8). Zunächst etwas Hintergrund. EIN funktionale Schnittstelle ist eine Schnittstelle, die genau eine abstrakte Methode hat, obwohl sie beliebig viele enthalten kann Standardmethoden (neu in Java 8) und statische Methoden. Ein Lambda-Ausdruck kann die abstrakte Methode schnell implementieren, ohne die unnötige Syntax, die erforderlich ist, wenn Sie keinen Lambda-Ausdruck verwenden.

Ohne Lambda-Ausdrücke:

obj.aMethod(new AFunctionalInterface() {
    @Override
    public boolean anotherMethod(int i)
    {
        return i == 982
    }
});

Mit Lambda-Ausdrücken:

obj.aMethod(i -> i == 982);

Hier ein Auszug aus das Java-Tutorial zu Lambda-Ausdrücken:

Syntax von Lambda-Ausdrücken

Ein Lambda-Ausdruck besteht aus Folgendem:

  • Eine durch Kommas getrennte Liste formaler Parameter, die in Klammern eingeschlossen sind. Die CheckPerson.test-Methode enthält einen Parameter, p, der eine Instanz der Person-Klasse darstellt.

    Notiz: Sie können den Datentyp der Parameter in einem Lambda-Ausdruck weglassen. Außerdem können Sie die Klammern weglassen, wenn es nur einen Parameter gibt. Der folgende Lambda-Ausdruck ist beispielsweise auch gültig:

    p -> p.getGender() == Person.Sex.MALE 
        && p.getAge() >= 18
        && p.getAge() <= 25
    
  • Der Pfeilmarker, ->

  • Ein Körper, der aus einem einzelnen Ausdruck oder einem Anweisungsblock besteht. Dieses Beispiel verwendet den folgenden Ausdruck:

    p.getGender() == Person.Sex.MALE 
        && p.getAge() >= 18
        && p.getAge() <= 25
    

    Wenn Sie einen einzelnen Ausdruck angeben, wertet die Java-Laufzeitumgebung den Ausdruck aus und gibt dann seinen Wert zurück. Alternativ können Sie eine return-Anweisung verwenden:

    p -> {
        return p.getGender() == Person.Sex.MALE
            && p.getAge() >= 18
            && p.getAge() <= 25;
    }
    

    Eine return-Anweisung ist kein Ausdruck; In einem Lambda-Ausdruck müssen Sie Anweisungen in geschweiften Klammern ({}) einschließen. Sie müssen einen void-Methodenaufruf jedoch nicht in geschweiften Klammern einschließen. Folgendes ist beispielsweise ein gültiger Lambda-Ausdruck:

    email -> System.out.println(email)
    

Beachten Sie, dass ein Lambda-Ausdruck einer Methodendeklaration sehr ähnlich sieht; Sie können Lambda-Ausdrücke als anonyme Methoden betrachten – Methoden ohne Namen.


So können Sie eine Methode mit einem Lambda-Ausdruck „übergeben“:

Hinweis: Dies verwendet eine neue Standard-Funktionsschnittstelle, java.util.function.IntConsumer.

class A {
    public static void methodToPass(int i) { 
        // do stuff
    }
}
import java.util.function.IntConsumer;

class B {
    public void dansMethod(int i, IntConsumer aMethod) {
        /* you can now call the passed method by saying aMethod.accept(i), and it
        will be the equivalent of saying A.methodToPass(i) */
    }
}
class C {
    B b = new B();

    public C() {
        b.dansMethod(100, j -> A.methodToPass(j));   //Lambda Expression here
    }
}

Das obige Beispiel lässt sich mit dem noch weiter verkürzen :: Operator.

public C() {
    b.dansMethod(100, A::methodToPass);
}

  • “Eine funktionale Schnittstelle ist eine Schnittstelle, die nur eine abstrakte Methode hat, obwohl sie eine beliebige Anzahl von Standardmethoden (neu in Java 8) und statische Methoden enthalten kann.” Was sagen Sie damit, dass wir in Java 8 jetzt statische Methoden haben können? bei Schnittstellen?

    – Celeritas

    25. Juli 2014 um 0:15 Uhr

  • @Celeritas Ja, ich habe es hier ausführlich erklärt.

    – Der Typ mit dem Hut

    25. Juli 2014 um 1:03 Uhr

  • j ist eine ganze Zahl?

    – Rupinderjeet

    13. September 2016 um 3:52 Uhr

  • @rupinderjeet47 Ja. Im Unterricht A, methodToPass() nimm ein int als Argument.

    – Der Typ mit dem Hut

    13. September 2016 um 15:40 Uhr

1646312234 6 Wie ubergebe ich eine Funktion als Parameter in Java duplicate
Nathan Hughes

Dank Java 8 müssen Sie die folgenden Schritte nicht ausführen, um eine Funktion an eine Methode zu übergeben, dafür sind Lambdas da, siehe Oracle Lambda Expression-Lernprogramm. Der Rest dieses Beitrags beschreibt, was wir früher tun mussten, um diese Funktionalität zu implementieren.

Normalerweise deklarieren Sie Ihre Methode so, dass sie eine Schnittstelle mit einer einzigen Methode verwendet, und übergeben dann ein Objekt, das diese Schnittstelle implementiert. Ein Beispiel sind Commons-Sammlungen, wo Sie Schnittstellen für Closure, Transformer und Predicate sowie Methoden haben, an die Sie Implementierungen dieser übergeben. Guava ist die neue verbesserte Commons-Sammlung, dort finden Sie entsprechende Schnittstellen.

Zum Beispiel hat commons-collections org.apache.commons.collections.CollectionUtils, das viele statische Methoden hat, die übergebene Objekte annehmen, um zufällig eines auszuwählen, es gibt eine namens exist mit dieser Signatur:

static boolean exists(java.util.Collection collection, Predicate predicate) 

Es nimmt ein Objekt, das das Interface Predicate implementiert, was bedeutet, dass es eine Methode darauf haben muss, die irgendein Objekt nimmt und einen booleschen Wert zurückgibt.

Also ich kann es so nennen:

CollectionUtils.exists(someCollection, new Predicate() {
    public boolean evaluate(Object object) { 
        return ("a".equals(object.toString());
    }
});

und es gibt wahr oder falsch zurück, je nachdem, ob someCollection enthält ein Objekt, für das das Prädikat wahr zurückgibt.

Wie auch immer, dies ist nur ein Beispiel, und Commons-Sammlungen sind veraltet. Ich vergesse nur das Äquivalent in Guava.

1646312235 946 Wie ubergebe ich eine Funktion als Parameter in Java duplicate
amalloy

Java unterstützt Closures ganz gut. Es unterstützt einfach nicht Funktionen, daher ist die Syntax, an die Sie für Closures gewöhnt sind, viel umständlicher und sperriger: Sie müssen alles in einer Klasse mit einer Methode zusammenfassen. Zum Beispiel,

public Runnable foo(final int x) {
  return new Runnable() {
    public void run() {
      System.out.println(x);
    }
  };
}

Gibt ein ausführbares Objekt zurück, dessen run() Methode “schließt über” die x übergeben, genau wie in jeder Sprache, die erstklassige Funktionen und Closures unterstützt.

Wie ubergebe ich eine Funktion als Parameter in Java duplicate
c0der

Ich habe das Befehlsmuster verwendet, das @jk. erwähnt, Hinzufügen eines Rückgabetyps:

public interface Callable<I, O> {

    public O call(I input);   
}

Wie ubergebe ich eine Funktion als Parameter in Java duplicate
c0der

Ich weiß, dass dies ein ziemlich alter Beitrag ist, aber ich habe eine andere etwas einfachere Lösung. Sie könnten eine andere Klasse darin erstellen und sie abstrakt machen. Als nächstes erstellen Sie eine Abstract-Methode, die Sie nach Belieben benennen kann. Erstellen Sie in der ursprünglichen Klasse eine Methode, die die neue Klasse als Parameter verwendet. Rufen Sie in dieser Methode die abstrakte Methode auf. Es wird in etwa so aussehen.

public class Demo {

    public Demo(/.../){

    }

    public void view(Action a){
        a.preform();
    }

    /**
     * The Action Class is for making the Demo
     * View Custom Code
     */
    public abstract class Action {

        public Action(/.../){

        }

        abstract void preform();
    }
}

Jetzt können Sie so etwas tun, um eine Methode innerhalb der Klasse aufzurufen.

/...
Demo d = new Demo;
Action a = new Action() {

    @Override
    void preform() {
        //Custom Method Code Goes Here
    }
};

/.../
d.view(a)

Wie ich schon sagte, ich weiß, dass es alt ist, aber so denke ich, ist es ein bisschen einfacher. Ich hoffe es hilft.

  • Ihre Lösung bietet keine einfachere Methode. Die Verwendung einer bereits vorhandenen Schnittstelle zum Ausführen dieser Aufgabe ist intuitiver als das Erstellen einer eigenen benutzerdefinierten abstrakten Klasse. Obwohl an Ihrer Lösung nichts auszusetzen ist und eine Alternative bietet, sehe ich weder den Wert noch den Grund für die Verwendung dieses Ansatzes über eine Schnittstelle.

    – Jyro117

    7. August 2013 um 17:31 Uhr

  • Nach dem, was ich in den Interface-Beispielen gesehen habe, können Sie nur Rückgabewerte verwenden. Dies ist eher darauf ausgerichtet, wenn Sie ein ungültiges Ergebnis wünschen. In bestimmten Fällen könnte diese Alternative einige vorteilhafte Verwendungen haben.

    – Zatran

    7. August 2013 um 18:16 Uhr

  • Callable funktioniert gut für diese Situation oder einfach mit Runnable. Es ist üblicher, eine Schnittstelle zu verwenden, selbst wenn Sie eine benutzerdefinierte erstellt haben, da sie eine flexiblere Hierarchie bietet.

    – Jyro117

    7. August 2013 um 20:50 Uhr

923600cookie-checkWie übergebe ich eine Funktion als Parameter in Java? [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy