Heim Java javaLernprogramm Beschreibung der Lambda-Ausdruckssyntax in Java

Beschreibung der Lambda-Ausdruckssyntax in Java

Jan 23, 2017 pm 03:42 PM
java lambda表达式

Syntaxbeschreibung

Ein Lambda-Ausdruck besteht aus den folgenden Teilen:

1. Eine durch Kommas getrennte Liste formaler Parameter in Klammern. Die CheckPerson.test-Methode enthält einen Parameter p, der eine Instanz der Person-Klasse darstellt. Hinweis: Der Typ des Parameters im Lambda-Ausdruck kann weggelassen werden. Wenn nur ein Parameter vorhanden ist, können außerdem auch die Klammern weggelassen werden. Zum Beispiel der im vorherigen Abschnitt erwähnte Code:

p -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
    && p.getAge() <= 25
Nach dem Login kopieren

2. Pfeilsymbol: ->. Wird verwendet, um Parameter und Funktionskörper zu trennen.

3. Funktionskörper. Besteht aus einem Ausdruck oder Codeblock. Im Beispiel im vorherigen Abschnitt wurde ein Ausdruck wie dieser verwendet:

   
p.getGender() == Person.Sex.MALE
      && p.getAge() >= 18
      && p.getAge() <= 25
Nach dem Login kopieren

Wenn ein Ausdruck verwendet wird, berechnet die Java-Laufzeit den Wert des Ausdrucks und gibt ihn zurück. Darüber hinaus können Sie auch die Return-Anweisung im Codeblock verwenden:

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

Die Return-Anweisung ist jedoch kein Ausdruck. In Lambda-Ausdrücken müssen Anweisungen in geschweifte Klammern eingeschlossen werden. Es ist jedoch nicht erforderlich, Anweisungen in geschweifte Klammern einzuschließen, wenn nur eine Methode aufgerufen wird, die einen Nullwert zurückgibt. Daher ist auch die folgende Schreibweise korrekt:

email -> System.out.println(email)
Nach dem Login kopieren

Lambda-Ausdrücke und Methodendeklarationen sehen sehr ähnlich aus. Daher können Lambda-Ausdrücke auch als anonyme Methoden betrachtet werden, also als Methoden ohne definierten Namen.

Die oben genannten Lambda-Ausdrücke sind alle Ausdrücke, die nur einen Parameter als formalen Parameter verwenden. Die folgende Instanzklasse, Caulator, demonstriert, wie mehrere Parameter als formale Parameter verwendet werden:

package com.zhyea.zytools;
 
public class Calculator {
 
  interface IntegerMath {
    int operation(int a, int b);
  }
 
  public int operateBinary(int a, int b, IntegerMath op) {
    return op.operation(a, b);
  }
 
  public static void main(String... args) {
    Calculator myApp = new Calculator();
    IntegerMath addition = (a, b) -> a + b;
    IntegerMath subtraction = (a, b) -> a - b;
    System.out.println("40 + 2 = " + myApp.operateBinary(40, 2, addition));
    System.out.println("20 - 10 = " + myApp.operateBinary(20, 10, subtraction));
  }
}
Nach dem Login kopieren

Die Methode „operateBinary“ im Code verwendet zwei ganzzahlige Parameter, um arithmetische Operationen auszuführen. Die Rechenoperation hier selbst ist eine Instanz der IntegerMath-Schnittstelle. Im obigen Programm werden zwei arithmetische Operationen mithilfe von Lambda-Ausdrücken definiert: Addition und Subtraktion. Das Ausführungsprogramm gibt den folgenden Inhalt aus:

40 + 2 = 42
20 - 10 = 10
Nach dem Login kopieren

Zugriff auf lokale Variablen externer Klassen

Ähnlich wie lokale Klassen oder anonyme Klassen können Lambda-Ausdrücke auch auf lokale Variablen externer Klassen zugreifen Klassen . Der Unterschied besteht darin, dass bei der Verwendung von Lambda-Ausdrücken keine Probleme wie das Überschreiben berücksichtigt werden müssen. Ein Lambda-Ausdruck ist lediglich ein lexikalisches Konzept, was bedeutet, dass er weder Namen von der Oberklasse erben muss noch neue Bereiche einführt. Das heißt, eine Deklaration innerhalb eines Lambda-Ausdrucks hat dieselbe Bedeutung wie eine Deklaration in seiner externen Umgebung. Dies wird im folgenden Beispiel demonstriert:

package com.zhyea.zytools;
 
import java.util.function.Consumer;
 
public class LambdaScopeTest {
 
  public int x = 0;
 
  class FirstLevel {
 
    public int x = 1;
 
    void methodInFirstLevel(int x) {
      //如下的语句会导致编译器在statement A处报错“local variables referenced from a lambda expression must be final or effectively final”
      // x = 99;
      Consumer<integer> myConsumer = (y) ->{
        System.out.println("x = " + x); // Statement A
        System.out.println("y = " + y);
        System.out.println("this.x = " + this.x);
        System.out.println("LambdaScopeTest.this.x = " + LambdaScopeTest.this.x);
      };
 
      myConsumer.accept(x);
    }
  }
 
  public static void main(String... args) {
    LambdaScopeTest st = new LambdaScopeTest();
    LambdaScopeTest.FirstLevel fl = st.new FirstLevel();
    fl.methodInFirstLevel(23);
  }
}
Nach dem Login kopieren


Dieser Code gibt Folgendes aus:

   
x = 23
y = 23
this.x = 1
LambdaScopeTest.this.x = 0
Nach dem Login kopieren


Wenn der Parameter y im Lambda-Ausdruck myConsumer im Beispiel durch x ersetzt wird, meldet der Compiler einen Fehler:

Consumer<integer> myConsumer = (x) ->{
      // ....
    };
Nach dem Login kopieren


The Die Compiler-Fehlermeldung lautet: „Variable x ist bereits in der Methode methodInFirstLevel(int) definiert“, was bedeutet, dass die Variable x in der Methode methodInFirstLevel definiert wurde. Der Fehler wird gemeldet, weil Lambda-Ausdrücke keine neuen Bereiche einführen. Daher können Sie in Lambda-Ausdrücken direkt auf die Feldfelder, Methoden und formalen Parameter der externen Klasse zugreifen. In diesem Beispiel greift der Lambda-Ausdruck myConsumer direkt auf den formalen Parameter x der Methode methodInFirstLevel zu. Beim Zugriff auf Mitglieder externer Klassen verwenden Sie auch direkt das Schlüsselwort this. In diesem Beispiel bezieht sich this.x auf FirstLevel.x.

Lambda-Ausdrücke können jedoch wie lokale Klassen oder anonyme Klassen nur auf lokale Variablen oder externe Mitglieder zugreifen, die als final (oder äquivalent zu final) deklariert sind. Beispielsweise entfernen wir den Kommentar vor „x=99“ in der methodInFirstLevel-Methode im Beispielcode:

//如下的语句会导致编译器在statement A处报错“local variables referenced from a lambda expression must be final or effectively final”
x = 99;
Consumer<integer> myConsumer = (y) ->{
  System.out.println("x = " + x); // Statement A
  System.out.println("y = " + y);
  System.out.println("this.x = " + this.x);
  System.out.println("LambdaScopeTest.this.x = " + LambdaScopeTest.this.x);
};
Nach dem Login kopieren


Da der Wert des Parameters x geändert wird In dieser Anweisung wird dadurch der Parameter x von methodInFirstLevel nicht mehr als endgültig betrachtet. Daher meldet der Java-Compiler einen Fehler wie „Lokale Variablen, auf die von einem Lambda-Ausdruck verwiesen wird, müssen endgültig oder tatsächlich endgültig sein“, wenn der Lambda-Ausdruck auf die lokale Variable x zugreift.

Zieltyp

So bestimmen Sie den Typ des Lambda-Ausdrucks. Werfen wir einen Blick auf den Code für die Überprüfung von Personal im Wehrdienstalter:

   
p -> p.getGender() == Person.Sex.MALE
       && p.getAge() >= 18
       && p.getAge() <= 25
Nach dem Login kopieren


Dieser Code wurde an zwei Stellen verwendet:

public static void printPersons( List Roster, CheckPerson Tester) – Option 3
public void printPersonsWithPredicate(List Roster, Predicate Tester) – Option 6

Beim Aufrufen der printPersons Methode: Diese Methode erwartet einen Parameter vom Typ CheckPerson und der obige Ausdruck ist ein Ausdruck vom Typ CheckPerson. Beim Aufruf der printPersonsWithPredicate-Methode wird ein Parameter vom Typ Predicate erwartet, und derselbe Ausdruck ist vom Typ Predicate. Auf diese Weise wird der Typ, der durch den von der Methode erwarteten Typ bestimmt wird, als Zieltyp bezeichnet (tatsächlich denke ich, dass die Typinferenz in Scala hier besser geeignet ist). Der Java-Compiler bestimmt den Typ eines Lambda-Ausdrucks anhand des Kontexts des Zieltyps oder der Position, an der sich der Lambda-Ausdruck befindet. Das bedeutet, dass Lambda-Ausdrücke nur dort verwendet werden können, wo der Java-Compiler den Typ

Variable Deklaration

Return Statement; Array-Initialisierung;

Methoden- oder Konstruktorparameter;

Bedingter Ausdruck (?:);

Zieltyp und Methodenparameter

对于方法参数,Java编译器还需要依赖两个语言特性来决定目标类型:重载解析和类型参数推断。

看一下下面的这两个函数式接口( java.lang.Runnable and java.util.concurrent.Callable):

public interface Runnable {
    void run();
  }
 
  public interface Callable<v> {
    V call();
  }
Nach dem Login kopieren


Runnable.run()方法没有返回值,而Callable.call()方法有。

假设我们像下面这样重载了invoke方法:

void invoke(Runnable r) {
   r.run();
 }
 
 <t> T invoke(Callable<t> c) {
   return c.call();
 }
Nach dem Login kopieren


那么在下面的语句中将会调用哪个方法呢:

String s = invoke(() -> "done");

调用的是invoke(Callable),因为这个方法有返回值,而invoke(Runnable)没有返回值。在这种情况下lambda表达式(() -> “done”)的类型是Callable

序列化

如果一个lambda表达式的目标类型还有它调用的参数的类型都是可序列化的,那么lambda表达式也是可序列化的。然而就像内部类一样,强烈不建议对lambda表达式进行序列化。

更多java中lambda表达式语法说明相关文章请关注PHP中文网!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Verursacht die Sicherheitssoftware des Unternehmens, die die Anwendung nicht ausführt? Wie kann man es beheben und es lösen? Verursacht die Sicherheitssoftware des Unternehmens, die die Anwendung nicht ausführt? Wie kann man es beheben und es lösen? Apr 19, 2025 pm 04:51 PM

Fehlerbehebung und Lösungen für die Sicherheitssoftware des Unternehmens, die dazu führt, dass einige Anwendungen nicht ordnungsgemäß funktionieren. Viele Unternehmen werden Sicherheitssoftware bereitstellen, um die interne Netzwerksicherheit zu gewährleisten. ...

Wie kann ich elegante Entitätsklassenvariablennamen erhalten, um Datenbankabfragebedingungen zu erstellen? Wie kann ich elegante Entitätsklassenvariablennamen erhalten, um Datenbankabfragebedingungen zu erstellen? Apr 19, 2025 pm 11:42 PM

Bei Verwendung von MyBatis-Plus oder anderen ORM-Frameworks für Datenbankvorgänge müssen häufig Abfragebedingungen basierend auf dem Attributnamen der Entitätsklasse erstellt werden. Wenn Sie jedes Mal manuell ...

Wie vereinfachte ich Probleme mit der Feldzuordnung im Systemdocking mithilfe des Mapstruct? Wie vereinfachte ich Probleme mit der Feldzuordnung im Systemdocking mithilfe des Mapstruct? Apr 19, 2025 pm 06:21 PM

Die Verarbeitung von Feldzuordnungen im Systemdocken stößt häufig auf ein schwieriges Problem bei der Durchführung von Systemdocken: So kartieren Sie die Schnittstellenfelder des Systems und ...

Wie konvertiere ich Namen in Zahlen, um die Sortierung zu implementieren und die Konsistenz in Gruppen aufrechtzuerhalten? Wie konvertiere ich Namen in Zahlen, um die Sortierung zu implementieren und die Konsistenz in Gruppen aufrechtzuerhalten? Apr 19, 2025 pm 11:30 PM

Lösungen zum Umwandeln von Namen in Zahlen zur Implementierung der Sortierung in vielen Anwendungsszenarien müssen Benutzer möglicherweise in Gruppen sortieren, insbesondere in einem ...

Wie identifiziert Intellij IDEA die Portnummer eines Spring -Boot -Projekts, ohne ein Protokoll auszugeben? Wie identifiziert Intellij IDEA die Portnummer eines Spring -Boot -Projekts, ohne ein Protokoll auszugeben? Apr 19, 2025 pm 11:45 PM

Beginnen Sie den Frühling mit der Intellijideaultimate -Version ...

Wie kann ich elegant den variablen Entitätsklassennamen erstellen, wenn Tkmybatis für Datenbankabfrage verwendet werden? Wie kann ich elegant den variablen Entitätsklassennamen erstellen, wenn Tkmybatis für Datenbankabfrage verwendet werden? Apr 19, 2025 pm 09:51 PM

Wenn Sie TKMybatis für Datenbankabfragen verwenden, ist das Aufbau von Abfragebedingungen ein häufiges Problem. Dieser Artikel wird ...

Wie kann ich Java -Objekte sicher in Arrays umwandeln? Wie kann ich Java -Objekte sicher in Arrays umwandeln? Apr 19, 2025 pm 11:33 PM

Konvertierung von Java-Objekten und -Arrays: Eingehende Diskussion der Risiken und korrekten Methoden zur Konvertierung des Guss-Typs Viele Java-Anfänger werden auf die Umwandlung eines Objekts in ein Array stoßen ...

Wie verwendet ich die Redis -Cache -Lösung, um die Anforderungen der Produktranking -Liste effizient zu erkennen? Wie verwendet ich die Redis -Cache -Lösung, um die Anforderungen der Produktranking -Liste effizient zu erkennen? Apr 19, 2025 pm 11:36 PM

Wie erkennt die Redis -Caching -Lösung die Anforderungen der Produktranking -Liste? Während des Entwicklungsprozesses müssen wir uns häufig mit den Anforderungen der Ranglisten befassen, z. B. das Anzeigen eines ...

See all articles