Ich bin liitFeet, ein serverseitiger Ingenieur. Vor kurzem habe ich Lust auf Coroutine WebFlux ausschließlich mit Kotlin und Spring Boot. Coroutine schwierig ...
Dieser Artikel ist der 7. Tag des TeamLab Engineering-Adventskalenders.
In diesem Artikel werde ich den Ursprung von Java-Lambda-Ausdrücken erläutern. Eh jetzt? Es gibt ein solches Gefühl, aber jetzt, da ich Funktionen wie go und kotlin als erstklassige Objekte verarbeiten kann, dachte ich, dass ich den Inhalt des Lambda-Ausdrucks tatsächlich verwende, ohne zu wissen, was es ist.
Unter dem Strich implementieren Java-Lambda-Ausdrücke eine Schnittstelle mit nur einer Methode zum Erstellen einer Instanz (neu). Ich halte diese Erklärung nicht für verwirrend, daher erkläre ich den Vorgang bis zum Lambda-Ausdruck der Reihe nach anhand eines Programms, das das Ergebnis der Berechnung eines bestimmten Ausdrucks als Beispiel anzeigt.
Ich denke, es ist einfacher zu verstehen, wenn Sie wissen, dass Lambda-Ausdrücke sowohl für Menschen als auch für Compiler leicht zu lesen sind, während die Anzahl der Beschreibungen reduziert wird.
In diesem Artikel wird auch der Ursprung von Java-Lambda-Ausdrücken beschrieben. Bitte beachten Sie, dass wir den Lambda-Ausdruck selbst nicht im Detail erklären werden (wenn es nur ein Argument gibt, müssen Sie keine Klammern, Funktionsschnittstellen usw. schreiben).
Den Quellcode finden Sie unter GitHub.
Zunächst möchte ich ein Programm realisieren, das das berechnete Ergebnis durch Übergeben einer normalen Klasse anzeigt. Der Quellcode ist das normalClass-Paket. Es gibt vier Quellen unten.
Main.Java Hauptklasse
Display.Java-Klasse zur Anzeige des Berechnungsergebnisses
CalcuratorInterface.Für die Java-Berechnung definierte Schnittstelle
Display.java CalcuratorInterface
Zunächst erhält sie in der Anzeigeklasse den für die Berechnung zuständigen Rechner und den zu berechnenden Wert (a, b). Berechnen Sie den Wert von (a, b) und zeigen Sie ihn mit dem Taschenrechner an.
public class Display {
public void showCalc(CalculatorInterface calculator, int a, int b) {
System.out.println(calculator.calc(a, b));
}
}
CalculatorInterface definiert calc, eine Methode, die Berechnungen durchführt.
public interface CalculatorInterface {
int calc(int a, int b);
}
AddCalculator implementiert CalculatorInterface und gibt die Summe der Argumente (a, b) zurück.
public class AddCalculator implements CalculatorInterface {
@Override
public int calc(int a, int b) {
return a + b;
}
}
In der Hauptklasse wird das Berechnungsergebnis angezeigt, indem der berechnete Wert als `` `Rechner``` an die Anzeigeklasse übergeben wird.
public class Main {
public static void main(String[] args) {
Display display = new Display();
CalculatorInterface calculator = new AddCalculator();
display.showCalc(calculator, 3, 5);
}
}
Ich denke, es gibt kein besonderes Problem.
Als nächstes möchte ich die innere Klasse verwenden. Der Quellcode ist das Paket innerClass. CalcuratorInterface.java und Display.java bleiben unverändert.
Wenn Sie die oben erwähnte normale Klasse verwenden, halten Sie es nicht für problematisch, eine Klassendatei nur für den Zusatz zu erstellen, der nur für die Hauptklasse verwendet wird? Daher können Sie AddCalculator.java entfernen, indem Sie AddCalculator in Main wie unten gezeigt definieren.
public class Main {
public static void main(String[] args) {
Display display = new Display();
//Definiere die innere Klasse
class AddCalculator implements CalculatorInterface {
@Override
public int calc(int a, int b) {
return a + b;
}
}
CalculatorInterface calculator = new AddCalculator();
display.showCalc(calculator, 3, 5);
}
}
Als nächstes werden wir die anonyme Klasse verwenden. Der Quellcode ist das anonymInnerClass-Paket. Ich habe die innere Klasse verwendet und musste keine Klassendatei erstellen, aber wenn ich sie hier nur einmal verwende, muss ich diese Klasse nicht benennen. Lassen Sie uns daher die Klasse zum Zeitpunkt der Zuweisung zum Taschenrechner vor Ort implementieren.
public class Main {
public static void main(String[] args) {
Display display = new Display();
//Einmal wegwerfbar
CalculatorInterface calculator = new CalculatorInterface() {
@Override
public int calc(int a, int b) {
return a + b;
}
};
display.showCalc(calculator, 3, 5);
}
}
Dies ist eine anonyme Klasse. Es kann nicht wiederverwendet werden, aber die Anzahl der Beschreibungen hat sich allmählich verringert.
Schließlich Argumente mit Lambda-Ausdrücken übergeben.
Der Quellcode lautet lambdaExpression Package.
Durch die Verwendung einer anonymen Klasse konnte ich den Namen der Klasse weglassen und die Anzahl der Beschreibungen reduzieren.
Wenn Sie jedoch CalculatorInterface implementieren, scheint es, dass der Compiler dies für Sie erledigt, ohne `new CalculatorInterface ()`
zu schreiben.
Wenn es nur eine Methode gibt, wird außerdem eindeutig bestimmt, welche Methode implementiert werden soll.
Der Typ des Methodenarguments wird auch in der Schnittstelle definiert, und der Compiler kann auf den Typ schließen, ohne ihn zu deklarieren.
In Lambda-Ausdrücken können Sie eine Instanz erstellen, indem Sie nur die für die Implementierung erforderlichen Methoden schreiben.
public class Main {
public static void main(String[] args) {
Display display = new Display();
//Nur die Verarbeitung der zu implementierenden Methode
CalculatorInterface calculator = (a, b) -> {
return a + b;
};
display.showCalc(calculator, 3, 5);
}
}
Der Lambda-Ausdruck ist der folgende Teil. Dieser Teil stellt die Implementierung der calc-Methode von CalculatorInterface dar.
(a, b) -> {
return a + b;
};
(a, b)
Ist ein Argument. Ich mache mir nicht die Mühe, das Methodenargument zu schreiben, da der Typ in der Schnittstelle definiert ist.
->
Das Folgende ist die Implementierung der Methode.a+b
Kommt zurück.
Was haben Sie gedacht. Ich hoffe, Sie können die Bedeutung des Schreibens "Java Lambda-Ausdruck implementiert eine Schnittstelle mit nur einer Methode und erstellt eine Instanz (neu)" am Anfang verstehen!
Es ist eine völlige Seite, aber es wäre schön, wenn Sie die Funktion als erstklassiges Objekt wie Kotlin behandeln könnten ... Die Argumente sind leicht zu verstehen ...
val calculator = {a: Int, b: Int -> a + b}
showCalc(calculator, 3, 5)
fun showCalc(calc: (Int, Int) -> Int, a: Int, b: Int) {
println(calc.invoke(a, b))
}
Recommended Posts