람다

람다 정의

  • 자바 8부터 도입된 람다는 자바에서 함수형 프로그래밍을 지원하기 위한 핵심 기능이다.

  • 람다는 익명 함수이다. 따라서 이름 없이 함수를 표현한다.

보통 메서드나 함수는 다음과 같이 표현한다.

반환타입 메서드명(매개변수) {
    본문
}

람다는 다음과 같이 간결하게 표현한다.

(매개변수) -> {본문}
//이름이 없는 함수

자바는 독립적인 함수를 지원하지 않으며, 메서드는 반드시 클래스나 인터페이스에 속한다.

👆 용어 - 람다와 람다식

  • 람다 (Lambda) : 익명 함수를 지칭하는 일반적인 용어 (개념)

  • 람다식 (Lambda Expression) : (매개변수) -> {본문} 형태로 람다를 구현하는 구체적인 문법 표현을 지칭한다.

람다는 개념을 의미하고(넓은 의미), 람다식은 자바에서 그 개념을 구현하는 구체적인 문법을 의미한다.

람다는 변수처럼 다룰 수 있다.

Procedure procedure = () -> { // 람다를 변수에 담음
    System.out.println("hello! lambda");
};

procedure.run(); // 변수를 통해 람다를 실행

람다도 익명 클래스처럼 클래스가 만들어지고, 인스턴스가 생성된다.

익명 클래스의 경우 $로 구분하며 뒤에 숫자가 붙고, 람다의 경우 $$로 구분하며 뒤에 복잡한 문자가 붙는다.


함수형 인터페이스

  • 함수형 인터페이스는 정확히 하나의 추상 메서드를 가지는 인터페이스를 말한다.

  • 람다는 클래스, 추상 클래스에는 할당할 수 없다. 오직 단일 추상 메서드를 가지는 함수형 인터페이스에만 할당할 수 있다.

  • 람다는 하나의 함수이다. 따라서 람다를 인터페이스에 담으려면 하나의 메서드(함수) 선언만 존재해야 한다.

  • 인터페이스는 여러 메서드(함수)를 선언할 수 있는데, 이 중 하나에 할당해야 하는 문제가 발생한다.

  • 자바는 이러한 문제를 해결하기 위해 단 하나의 추상 메서드만을 포함하는 함수형 인터페이스에만 람다를 할당할 수 있도록 제한했다.

👆 @FunctionalInterface

  • 이 애노테이션을 통해 함수형 인터페이스임을 선언해두면 나중에 실수로 추상 메서드를 추가할 때 컴파일 오류가 발생한다.

  • 따라서 함수형 인터페이스임을 보장할 수 있다.

  • 람다를 사용할 함수형 인터페이스라면 @FunctionalInterface 애노테이션을 필수로 추가하는 것을 권장한다.


람다와 시그니처

람다를 함수형 인터페이스에 할당할 때는 메서드의 형태를 정의하는 요소인 메서드 시그니처가 일치해야 한다.

메서드의 시그니처

  • 이름 : apply

  • 매개변수 : int, int

  • 반환 타입 : int

람다는 익명 함수이므로 시그니처에서 이름은 제외한다. 그 외 매개변수, 반환 타입이 함수형 인터페이스에 선언한 메서드와 맞아야 한다. (매개변수 이름은 상관없다. 타입과 순서만 맞으면 된다.)

또 다른 예시

  • 이름 : run

  • 매개변수 : 없음

  • 반환 타입 : 없음

람다 생략

람다는 간결하게 코드를 작성할 수 있는 다양한 문법 생략을 지원한다.

매개변수와 반환 값이 없는 경우

타입 추론

  • 이 함수형 인터페이스를 보면 이미 (int a, int b)로 매개변수의 타입이 정의되어 있다.

  • 이 정보를 사용하면 람다에서 타입 정보를 생략할 수 있다.

  • 자바 컴파일러는 람다가 사용되는 함수형 인터페이스의 메서드 타입을 기반으로 람다의 매개변수와 반환값의 타입을 추론한다. 따라서 람다는 타입을 생략할 수 있다.

  • 반환 타입은 문법적으로 명시할 수 없다. 대신에 컴파일러가 자동으로 추론한다.

매개변수 괄호 생략

  • 매개변수가 정확히 하나이면서 타입을 생략하고 이름만 있는 경우 소괄호(())를 생략할 수 있다.

  • 매개변수가 없는 경우 또는 매개변수가 둘 이상이면 ()가 필수이다.


람다의 전달

람다는 함수형 인터페이스를 통해 변수에 대입하거나 메서드에 전달하거나 반환할 수 있다.

  • 기본형이나 참조형이 변수에 값을 대입할 수 있는 것처럼 함수형 인터페이스로 선언한 변수에 람다 인스턴스의 참조값을 대입할 수 있다.

  • 람다도 인터페이스(함수형 인터페이스)를 사용하므로 람다 인스턴스의 참조값을 변수에 전달할 수 있다.

  • 변수에 참조값을 전달할 수 있으므로 다음과 같은 사용이 가능하다.

    • 매개변수를 통해 메서드(함수)에 람다를 전달할 수 있다. (정확히는 람다 인스턴스의 참조값을 전달)

    • 메서드가 람다를 반환할 수 있다. (정확히는 람다 인스턴스의 참조값을 반환)

람다를 메서드에 전달

메서드가 람다를 반환

  • 람다는 함수형 인터페이스를 구현한 익명 클래스 인스턴스와 같은 개념이다.

  • 람다를 변수에 대입한다는 것은 람다 인스턴스의 참조값을 대입하는 것이고, 람다를 메서드(함수)의 매개변수나 반환값으로 넘긴다는 것 역시 람다 인스턴스의 참조값을 전달, 반환하는 것이다.

  • 람다를 자유롭게 전달하거나 반환할 수 있기 때문에 코드의 간결성과 유연성이 높아진다. 만약 익명 클래스를 작성했다면 매우 번잡했을 것이다.

👆 고차 함수 (Higher-Order Function)

고차 함수는 함수를 값처럼 다루는 함수를 의미하며, 일반적으로 다음 두 가지 중 하나를 만족하면 고차 함수라 한다.

  1. 함수를 인자로 받는 함수(메서드)

  2. 함수를 반환하는 함수(메서드)

자바에서 람다(익명 함수)는 함수형 인터페이스를 통해서만 전달할 수 있다. 즉 자바에서 함수를 주고받는다는 것은 함수형 인터페이스를 구현한 어떤 객체(람다 or 익명 클래스)를 주고받는 것과 같다.

고차 함수함수를 다루는 추상화 수준이 더 높다는 데에서 유래했다. 보통 일반적인 함수는 데이터(값)을 다루는데, 이것을 넘어 함수라는 개념 자체를 값처럼 다룬다는 점에서 추상화의 수준이 한 단계 높아진다고 해서 고차 함수라고 부른다.

Last updated