Java java지도 시간 Java의 람다 표현식 구문 설명

Java의 람다 표현식 구문 설명

Jan 23, 2017 pm 03:42 PM
자바 람다 표현식

구문 설명

람다 표현식은 다음 부분으로 구성됩니다.

1. 괄호 안의 쉼표로 구분된 형식 매개변수 목록입니다. CheckPerson.test 메소드에는 Person 클래스의 인스턴스를 나타내는 매개변수 p가 포함되어 있습니다. 참고: 람다 식에서 매개 변수의 유형은 생략할 수 있으며, 매개 변수가 하나만 있는 경우 괄호도 생략할 수 있습니다. 예를 들어 이전 섹션에서 언급한 코드:

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
로그인 후 복사

표현식이 사용되면 Java 런타임은 표현식의 값을 계산하고 반환합니다. 또한 코드 블록에서 return 문을 사용하도록 선택할 수도 있습니다.

p -> {
  return p.getGender() == Person.Sex.MALE
      && p.getAge() >= 18
      && p.getAge() <= 25;
}
로그인 후 복사

그러나 return 문은 표현식이 아닙니다. 람다 식에서는 문을 중괄호로 묶어야 합니다. 그러나 null 값을 반환하는 메서드를 호출하는 경우에는 문을 중괄호로 묶을 필요가 없으므로 다음과 같이 쓰는 것도 맞습니다. >람다 표현식과 메소드 선언은 매우 비슷해 보입니다. 따라서 람다 식은 익명 메서드, 즉 정의된 이름이 없는 메서드로 간주될 수도 있습니다.

위에서 언급한 람다 표현식은 모두 하나의 매개변수만을 형식 매개변수로 사용하는 표현식입니다. 다음 인스턴스 클래스인 Caulator는 여러 매개변수를 형식 매개변수로 사용하는 방법을 보여줍니다.

email -> System.out.println(email)
로그인 후 복사

코드의 OperaBinary 메소드는 두 개의 정수 매개변수를 사용하여 산술 연산을 수행합니다. 여기서 산술 연산 자체는 IntegerMath 인터페이스의 인스턴스입니다. 위 프로그램에서는 람다 식을 사용하여 두 가지 산술 연산인 덧셈과 뺄셈을 정의합니다. 실행 프로그램은 다음을 인쇄합니다.

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));
  }
}
로그인 후 복사

외부 클래스의 지역 변수에 액세스


로컬 클래스나 익명 클래스와 마찬가지로 람다 식도 외부 클래스의 지역 변수에 액세스할 수 있습니다. 차이점은 람다 식을 사용할 때 덮어쓰기 등의 문제를 고려할 필요가 없다는 점입니다. 람다 식은 단지 어휘 개념일 뿐입니다. 즉, 슈퍼클래스에서 이름을 상속받을 필요도 없고 새로운 범위를 도입할 필요도 없습니다. 즉, 람다 식 내의 선언은 외부 환경의 선언과 동일한 의미를 갖습니다. 이는 다음 예에서 설명됩니다.

40 + 2 = 42
20 - 10 = 10
로그인 후 복사


이 코드는 다음을 출력합니다.

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);
  }
}
로그인 후 복사


예제에서 람다 식 myConsumer의 매개 변수 y가 x로 바뀌면 컴파일러는 오류를 보고합니다.

   
x = 23
y = 23
this.x = 1
LambdaScopeTest.this.x = 0
로그인 후 복사


컴파일러 오류 메시지는 " 변수 x는 이미 methodInFirstLevel(int) 메소드에 정의되어 있습니다. 이는 변수 x가 메소드 methodInFirstLevel에 정의되었음을 의미합니다. 람다 표현식이 새 범위를 도입하지 않기 때문에 오류가 보고됩니다. 따라서 람다 식에서 외부 클래스의 필드 필드, 메서드 및 형식 매개 변수에 직접 액세스할 수 있습니다. 이 예에서 람다 식 myConsumer는 methodInFirstLevel 메서드의 형식 매개 변수 x에 직접 액세스합니다. 외부 클래스의 멤버에 액세스할 때 this 키워드를 직접 사용할 수도 있습니다. 이 예에서 this.x는 FirstLevel.x를 나타냅니다.

그러나 로컬 클래스나 익명 클래스와 마찬가지로 람다 식은 final(또는 final과 동일)로 선언된 로컬 변수나 외부 멤버에만 액세스할 수 있습니다. 예를 들어 샘플 코드의 methodInFirstLevel 메소드에서 "x=99" ​​앞에 있는 주석을 제거합니다.

Consumer<integer> myConsumer = (x) ->{
      // ....
    };
로그인 후 복사


여기서 매개변수 x의 값이 수정되기 때문입니다. 명령문, methodInFirstLevel 매개변수 x는 더 이상 최종으로 간주될 수 없습니다. 따라서 Java 컴파일러는 람다 표현식이 로컬 변수 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);
};
로그인 후 복사


이 코드는 두 곳에서 사용되었습니다:

public static void printPersons (List roster, CheckPerson tester) - 옵션 3

public void printPersonsWithPredicate(List roster, Predicate tester) - 옵션 6



printPersons 메소드를 호출할 때, this 이 메소드는 CheckPerson 유형의 매개변수를 기대하며 위의 표현식은 CheckPerson 유형의 표현식입니다. printPersonsWithPredicate 메소드를 호출할 때 Predicate 유형의 매개변수가 예상되며 동일한 표현식은 Predicate 유형입니다. 이처럼 메소드에서 기대하는 타입에 따라 결정되는 타입을 타겟 타입(target type)이라고 합니다. (사실 여기서는 Scala의 타입 추론이 더 적합하다고 생각합니다.) Java 컴파일러는 대상 유형의 컨텍스트 또는 람다 표현식이 있는 위치를 통해 람다 표현식의 유형을 결정합니다. 이는 Java 컴파일러가 유형을 추론할 수 있는 경우에만 람다 표현식을 사용할 수 있음을 의미합니다.

할당;

배열 초기화;

메서드 또는 생성자 매개변수

람다 표현식 메소드 본문;

예외가 발생하는 경우.

대상 유형 및 메소드 매개변수

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

看一下下面的这两个函数式接口( 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表达式进行序列化。

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

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

회사의 보안 소프트웨어가 응용 프로그램이 실행되지 않습니까? 문제 해결 및 해결 방법은 무엇입니까? 회사의 보안 소프트웨어가 응용 프로그램이 실행되지 않습니까? 문제 해결 및 해결 방법은 무엇입니까? Apr 19, 2025 pm 04:51 PM

일부 애플리케이션이 제대로 작동하지 않는 회사의 보안 소프트웨어에 대한 문제 해결 및 솔루션. 많은 회사들이 내부 네트워크 보안을 보장하기 위해 보안 소프트웨어를 배포 할 것입니다. ...

데이터베이스 쿼리 조건을 구축하기 위해 엔티티 클래스 변수 이름을 우아하게 얻는 방법은 무엇입니까? 데이터베이스 쿼리 조건을 구축하기 위해 엔티티 클래스 변수 이름을 우아하게 얻는 방법은 무엇입니까? Apr 19, 2025 pm 11:42 PM

데이터베이스 작업에 MyBatis-Plus 또는 기타 ORM 프레임 워크를 사용하는 경우 엔티티 클래스의 속성 이름을 기반으로 쿼리 조건을 구성해야합니다. 매번 수동으로 ...

맵 구조를 사용하여 시스템 도킹에서 필드 매핑 문제를 단순화하는 방법은 무엇입니까? 맵 구조를 사용하여 시스템 도킹에서 필드 매핑 문제를 단순화하는 방법은 무엇입니까? Apr 19, 2025 pm 06:21 PM

시스템 도킹의 필드 매핑 처리 시스템 도킹을 수행 할 때 어려운 문제가 발생합니다. 시스템의 인터페이스 필드를 효과적으로 매핑하는 방법 ...

분류를 구현하고 그룹의 일관성을 유지하기 위해 이름을 숫자로 변환하려면 어떻게합니까? 분류를 구현하고 그룹의 일관성을 유지하기 위해 이름을 숫자로 변환하려면 어떻게합니까? Apr 19, 2025 pm 11:30 PM

많은 응용 프로그램 시나리오에서 정렬을 구현하기 위해 이름으로 이름을 변환하는 솔루션, 사용자는 그룹으로, 특히 하나로 분류해야 할 수도 있습니다.

Intellij Idea는 로그를 출력하지 않고 스프링 부팅 프로젝트의 포트 번호를 어떻게 식별합니까? Intellij Idea는 로그를 출력하지 않고 스프링 부팅 프로젝트의 포트 번호를 어떻게 식별합니까? Apr 19, 2025 pm 11:45 PM

IntellijideAultimate 버전을 사용하여 봄을 시작하십시오 ...

데이터베이스 쿼리에 tkmyBatis를 사용할 때 엔티티 클래스 변수 이름 빌드 쿼리 조건을 우아하게 얻는 방법은 무엇입니까? 데이터베이스 쿼리에 tkmyBatis를 사용할 때 엔티티 클래스 변수 이름 빌드 쿼리 조건을 우아하게 얻는 방법은 무엇입니까? Apr 19, 2025 pm 09:51 PM

데이터베이스 쿼리에 tkmyBatis를 사용하는 경우 쿼리 조건을 구축하기 위해 엔티티 클래스 변수 이름을 우아하게 가져 오는 방법이 일반적인 문제입니다. 이 기사는 고정 될 것입니다 ...

Java 객체를 어레이로 안전하게 변환하는 방법은 무엇입니까? Java 객체를 어레이로 안전하게 변환하는 방법은 무엇입니까? Apr 19, 2025 pm 11:33 PM

Java 객체 및 배열의 ​​변환 : 캐스트 유형 변환의 위험과 올바른 방법에 대한 심층적 인 논의 많은 Java 초보자가 객체를 배열로 변환 할 것입니다 ...

Redis 캐시 솔루션을 사용하여 제품 순위 목록의 요구 사항을 효율적으로 실현하는 방법은 무엇입니까? Redis 캐시 솔루션을 사용하여 제품 순위 목록의 요구 사항을 효율적으로 실현하는 방법은 무엇입니까? Apr 19, 2025 pm 11:36 PM

Redis 캐싱 솔루션은 제품 순위 목록의 요구 사항을 어떻게 인식합니까? 개발 과정에서 우리는 종종 a ... 표시와 같은 순위의 요구 사항을 처리해야합니다.

See all articles