java에서 lambda 표현식 문법 설명

7231 단어 javalambda 표현식
문법 설명
lambda 표현식은 다음과 같은 몇 가지 부분으로 구성됩니다.
1. 괄호 안에 쉼표로 구분된 인삼 목록.CheckPerson에서test 방법에는 Person 클래스의 실례를 나타내는 매개 변수 p가 포함되어 있습니다.주의:lambda 표현식의 매개 변수의 유형은 생략할 수 있습니다.또한 매개 변수가 하나만 있으면 괄호도 생략할 수 있다.예를 들어 지난 절에서 언급한 코드:

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

2. 화살표 기호: ->.매개 변수와 함수체를 구분하는 데 쓰인다.
3. 함수체.표현식이나 코드 블록으로 구성되어 있습니다.이전 절의 예에서는 다음과 같은 표현식을 사용했습니다.

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

표현식을 사용한다면, 자바가 실행될 때 표현식의 값을 계산하고 되돌려줍니다.또한 코드 블록에서 return 문구를 사용할 수도 있습니다.

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

그러나return 문장은 표현식이 아니다.lambda 표현식에서 문장을 괄호로 묶어야 하지만 반환값이 비어 있는 방법만 호출할 필요가 없기 때문에 괄호로 묶을 필요가 없습니다. 따라서 다음과 같은 문법도 정확합니다.

  email -> System.out.println(email)

lambda 표현식과 방법의 성명은 유사한 점이 많아 보인다.그래서 람다 표현식을 익명 방법, 즉 이름을 정의하지 않은 방법으로 볼 수도 있다.
위에서 언급한 lambda 표현식은 모두 하나의 매개 변수만 형삼으로 사용한 표현식이다.다음 인스턴스 클래스인 Caulator에서는 여러 매개변수를 인삼으로 사용하는 방법을 보여 줍니다.

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));
  }
}

코드에서operateBinary 방법은 두 개의 정형 매개 변수를 사용하여 산수 조작을 실행합니다.여기서 산수 작업 자체가 IntegerMath 인터페이스의 한 예입니다.위의 프로그램에서lambda 표현식을 사용하여 두 가지 산수 동작을 정의했습니다:addition과subtraction.실행 프로그램은 다음과 같은 내용을 인쇄합니다.

40 + 2 = 42
20 - 10 = 10

외부 클래스에 접근하는 국부 변수
국부 클래스나 익명 클래스와 유사하게lambda 표현식도 외부 클래스의 국부 변수에 접근할 수 있습니다.다른 것은lambda 표현식을 사용할 때 덮어쓰기와 같은 문제를 고려할 필요가 없다는 것이다.lambda 표현식은 하나의 어법상의 개념일 뿐이다. 이것은 초류에서 어떤 명칭도 계승할 필요가 없고 새로운 작용역을 도입하지 않는다는 것을 의미한다.즉, 람다 표현식에서의 성명과 외부 환경에서의 성명의 의미는 같다.다음 예제에서는 다음과 같이 설명합니다.

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);
  }
}

이 코드는 다음과 같이 출력됩니다.

x = 23
y = 23
this.x = 1
LambdaScopeTest.this.x = 0

예시에서 lambda 표현식 myConsumer의 매개 변수 y를 x로 바꾸면 컴파일러가 오류를 보고합니다.
 

  Consumer<integer> myConsumer = (x) ->{
        // ....
      };
컴파일러 오류 정보는 "variable x is already defined in method method InFirstLevel (int)"입니다. 방법 method InFirstLevel에서 변수 x를 정의했습니다.오류는 lambda 표현식이 새로운 작용역을 도입하지 않기 때문이다.따라서 lambda 표현식에서 외부 클래스의 필드, 방법, 인삼에 직접 접근할 수 있다.이 예에서 lambda 표현식 myConsumer는 방법 method InFirst Level의 인삼 x에 직접 접근했다.외부 클래스의 구성원에 접근할 때도this 키워드를 직접 사용합니다.이 예에서 this.x는 First Level을 가리킨다.x.
그러나 국부 클래스나 익명 클래스와 마찬가지로lambda 표현식도 국부 변수나 외부에서final(또는final과 같은) 구성원으로만 접근할 수 있습니다.예를 들어, 예제 코드 methodInFirstLevel 메서드에서 "x=99"앞에 있는 설명을 제거합니다.

      // 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);
      };
이 문장에서 매개 변수 x의 값을 수정했기 때문에methodInFirstLevel의 매개 변수 x는 더 이상final식으로 볼 수 없습니다.따라서 자바 컴파일러는 lambda 표현식이 국부 변수 x에 접근하는 곳에서 "local variables referenced from a lambda expression must be final or effectively final"같은 오류를 보고합니다.
대상 유형
람다 표현식의 유형을 어떻게 판단해야 하나요?다시 한 번 적령기 군 복무자를 선별하는 코드를 살펴보자.

   p -> p.getGender() == Person.Sex.MALE
          && p.getAge() >= 18
          && p.getAge() <= 25
이 코드는 두 곳에서 사용되었다.
public static void printPersons(Listroster, CheckPerson tester)―방안 3
public void printPersonsWithPredicate(Listroster, Predicatetester)―방안 6
printPersons 방법을 호출할 때, 이 방법은 CheckPerson 형식의 매개 변수를 기대합니다. 이때 위의 표현식은 CheckPerson 형식의 표현식입니다.printPersonsWithPredicate 방법을 호출할 때 Predicate 형식의 매개 변수를 기대합니다. 이때 같은 표현식이 Predicate 형식입니다.이와 같이 방법이 기대하는 유형에 따라 결정되는 유형을 목표 유형이라고 한다.자바 컴파일러는 목표 유형의 상하문 언어 환경이나 람다 표현식을 발견했을 때의 위치를 통해 람다 표현식의 유형을 판단하는 것이다.즉, Java 컴파일러에서만 Lambda 표현식을 사용하여 유형을 추정할 수 있습니다.
  • 변수 성명;
  • 부치;
  • 문장으로 돌아가기;
  • 수조 초기화;
  • 방법 또는 구조기 파라미터;
  • lambda 표현식 방법체;
  • 조건 표현식(?:);
  • 이상을 던질 때.
  • 대상 유형 및 메소드 매개변수
    방법 매개 변수에 대해 자바 컴파일러는 두 가지 언어 특성에 의존하여 목표 유형을 결정해야 한다. 즉, 재부팅 해석과 유형 매개 변수 추정이다.
    아래의 두 함수식 인터페이스 (java.lang.Runnable and java.util.concurrent.Callable) 를 보십시오.
    
    public interface Runnable {
        void run();
      }
    
      public interface Callable<v> {
        V call();
      }
    
    
    Runnable.run() 메서드는 반환 값이 없고 Callable입니다.call () 방법이 있습니다.
    만약 우리가 아래와 같이 invoke 방법을 다시 불러왔다면
    
     void invoke(Runnable r) {
        r.run();
      }
    
      <t> T invoke(Callable<t> c) {
        return c.call();
      }
    
    
    그러면 다음 문장에서 어떤 방법이 사용될까요?String s = invoke(() -> "done"); 호출된 것은 invoke(Callable)입니다. 이 방법은 반환 값이 있고, invoke(Runnable)는 반환 값이 없습니다.이 경우 lambda 표현식(() -> "done")의 유형은 Callable입니다.
    서열화
    만약lambda 표현식의 목표 형식과 호출된 매개 변수의 형식이 모두 서열화된다면lambda 표현식도 서열화될 수 있다.그러나 내부 클래스처럼 lambda 표현식에 대한 서열화를 강력히 권장하지 않습니다.

    좋은 웹페이지 즐겨찾기