JAVA/라이브 스터디 | whiteship

[live-study] 15주차 :: 람다식

0298 2021. 3. 6. 12:00

참고도서 : Java의 정석(3rd Edition), 이것이 자바다

 

 

 


0. 람다식

람다식 (Lambda Expression)
  • 람다식은 간단히 말해서 메소드를 하나의 식(expression)으로 표현한 것이다.
  • 자바 8부터 람다식을 지원하였다.
  • 람다식은 익명 함수(anonymous function)를 생성하기 위한 식으로 객체 지향 언어보다는 함수 지향 언어에 가깝다.
람다식 장점
  • 자바 코드가 매우 간결해졌다.
  • 컬렉션의 요소를 필터링하거나 매핑해서 원하는 결과를 쉽게 집계할 수 있다.

 

1. 람다식 사용법

람다식 형태
  • 람다식은 매개 변수를 가진 코드 블록이지만, 런타임 시에는 익명 구현 객체를 생성한다.

  • 예를 들어, Runnable 인터페이스의 익명 구현 객체를 생성하는 코드는 아래와 같다.
  • 람다식은 (매개변수) -> {실행코드} 형태로 작성되고, 런타임시에 인터페이스의 익명 구현 객체로 생성된다.

람다식 기본 문법
  • 람다식은 (타입 매개변수) -> {실행코드} 형태로 작성된다. 

  • 예를 들어, int 타입의 매개변수 a의 값을 출력하려면 다음과 같이 작성할 수 있다.

  • 그리고, 매개 변수 타입은 런타임 시에 대입되는 값에 따라 자동으로 인식될 수 있으므로, 일반적으로 언급하지 않는다.

  • 또한, 지금의 예제와 같이 매개 변수가 하나만 있다면 괄호를 생략할 수도 있고, 실행문이 하나만 있다면 중괄호 { }도 생략할 수 있다.

 

2. 함수형 인터페이스

함수형 인터페이스
  • 모든 인터페이스를 람다식의 타겟 타입으로 사용할 수는 없다.
  • 람다식이 하나의 메소드를 정의하기 때문에, 두 개 이상의 추상 메소드가 선언된 인터페이스는 람다식을 이용해서 구현 객체를 사용할 수가 없다.
  • 즉, 하나의 추상메소드가 선언된 인터페이스만이 람다식의 타겟 타입이 될 수 있다. 
  • 이러한 인터페이스를 함수형 인터페이스(Functional Interface)라고 한다.
  • 인터페이스 선언 시 @FunctionalInterface 어노테이션을 붙이는데, 두 개 이상의 추상 메소드가 선언되면 컴파일 오류를 발생시킨다.

 

3. Variable Capture

Variable Capture
  • Java 람다식은 어떠한 특정 상솽에서 람다 함수 body 외부에 선언된 변수에 접근할 수 있다.
  • 종류로는 로컬 변수, 인스턴스 변수, 정적 변수 캡쳐가 있다.
Local Variable 
  • Java 람다식은 함수 body 외부에 선언되어 있는 local 변수의 값에 접근할 수 있다.
  • 이 때 "effectively final"이어야 한다. effectively final이란 final이 붙어 있지 않은 변수의 값이 변경되지 않는 것을 말한다.

Instantce Variable
  • Java 람다식은 instance 변수에도 접근이 가능하다.
  • 람다 본문에 있는 this.name에 대한 참조를 살펴조면, 이는 EventConsumerImpl 오브젝트의 name 인스턴스 변수를 캡쳐한다.
  • 캡쳐 후 인스턴스의 변수 값을 변경할 수도 있으며 값은 람다 내부에도 반영이 된다.

Static Variable
  • Java 람다식은 또한 static 변수에도 접근을 할 수 있다. 하지만 사실 static 변수는 어디에서나 접근이 가능하기에 놀랄만한 일은 아니다.

 

4. 메소드, 생성자 레퍼런스

메소드 레퍼런스
  • 메소드 레퍼런스(Method References)는 말 그대로 메소드를 참조해서 매개 변수의 정보 및 리턴 타입을 알아내어, 람다식에 불필요한 매개 변수를 제거하는 것이 목적이다.
  • 예를 들어, 두 개의 값을 받아 더 큰 수를 리턴하는 Math 클래스의 max() 정적 메소드를 호출하는 람다식은 아래와 같다.

  • 여기서 람다식은 단순히 두 개의 값만을 Math.max() 메소드의 매개값으로 전달하는 역할만 하고 있다.
  • 그래서 아래와 같이 메소드 참조를 이용하여 간결하게 표현할 수 있다.

  • 람다식을 메소드 참조로 변환하는 방법을 다음과 같이 정리할 수 있다.

  • 즉, 하나의 메소드만 호출하는 람다식은 클래스이름::메소드이름 또는 참조변수::메소드이름으로 바꿀 수 있다.

 

생성자 레퍼런스
  • 메소드 레퍼런스는 생성자 레퍼런스(Method References)도 포함한다.
  • 생성자를 레퍼런스한다는 것은 객체 생성을 의미한다. 
  • 단순히 객체를 생성하고 리턴하도록 구성된 람다식은 생성자 참조로 대치할 수 있다.
  • 아래 코드는 단순히 객체 생성 후 리턴만 하는 것을 볼 수 있다.

  • 이런 경우, 생성자 참조로 표현하려면 클래스 이름 뒤에 :: 기호를 붙이고 new 연산자를 기술하면 된다.

 

 

참고자료