JAVA/JAVA

Java | Lambda Expression 람다식

pathas 2020. 2. 14. 00:36

Lambda Expression 람다식

자바에서 제공하는 함수형 프로그래밍 방식

  • 자바 8부터 함수형 프로그래밍 지원
  • Functional Programming(FP): 함수형 프로그래밍
    함수의 구현과 호출만으로 프로그램을 만들 수 있는 프로그래밍 방식
  • 함수 이름이 없는 익명 함수를 만드는 것

Lambda 문법

(매개변수) -> {실행 코드;}
  • 메소드 이름과 반환형을 없애고 -> 기호 사용
  • 매개변수 자료형 생략 가능
  • 매개변수가 하나인 경우에는 괄호 생략 가능
  • 중괄호 안의 구현 부분이 한 문장인 경우 중괄호 생략 가능
  • 중괄호 안의 구현부가 한 문장이더라도 return문은 중괄호 생략 불가
  • 중괄호 안의 구현부가 return문 하나라면 중괄호과 return을 모두 생략하고 식만 작성 가능

함수형 인터페이스

  • 자바에서는 참조 변수 없이 메소드를 호출할 수 없기 때문에
    람다식 구현을 위한 함수형 인터페이스가 필요
  • 람다식 구현을 위한 함수형 인터페이스를 만들고
    인터페이스에 람다식으로 구현할 메소드 선언
  • 람다식은 하나의 메소드를 구현하여 인터페이스형 변수에 대입하기 때문에
    인터페이스가 두 개 이상의 메소드를 가질 수 없음
  • 람다식은 익명 함수이기 때문에
    인터페이스에 메소드가 여러 개 있으면 구분이 불가능함

@FunctionalInterface 어노테이션

  • 인터페이스 바로 위에 @FunctionalInterface를 작성하면 함수형 인터페이스라는 뜻
  • 메소드를 하나 이상 선언하면 오류 발생
  • 필수로 작성해야 하는 것은 아니지만 함수형 인터페이스를 명시적으로 표현하므로
    나중에 발생할 오류를 방지할 수 있음

 

@FunctionalInterface
interface 인터페이스명 {}

람다식으로 인터페이스 구현

  • 클래스를 따로 생성할 필요 없이 바로 메소드 구현
  • 자바는 객체 지향 언어로 객체 생성 없이 메소드 호출 불가
    → 람다식으로 인터페이스 메소드 구현시
    컴퓨터 내부에서 익명 클래스를 통한 익명 객체 생성
  • 람다식 코드에서 외부 메소드 지역 변수 사용시 해당 변수는 상수로 작용
    따라서 외부 메소드의 지역 변수를 출력할 수는 있지만 변수 값 수정은 불가능
  • 람다식은 함수의 구현부를 변수에 대입하거나
    매개변수로 전달하거나 반환 값으로 사용 가능
    즉, 변수처럼 사용 가능

예제 ①

익명 내부 클래스와 람다식으로 함수형 인터페이스 구현

package j200213;

// 함수형 인터페이스
@FunctionalInterface
interface Xyz2 {
    public int a(int x, int y);
}

public class LamTest2 {

    public static void main(String[] args) {

        // 익명 내부 클래스로 인터페이스 구현
        Xyz2 anonymousInner = new Xyz2() {
            public int a(int x, int y) {
                return x + y;
            }
        };
        int resultA = anonymousInner.a(1, 9);

        System.out.println(resultA);    //10

        // 람다식으로 인터페이스 구현
        Xyz2 lambda = (x, y) -> x + y;
        int resultB = lambda.a(4, 5);

        System.out.println(resultB);    //9

    }

}

예제 ②

람다식을 인터페이스형 변수에 대입한 뒤 메소드를 호출해보고
다시 그 변수를 메소드의 매개변수로 전달하는 예제

package j200213;

@FunctionalInterface
interface Lambda {
    void showString(String str);
}

public class LamPara {

    public static void main(String[] args) {
        // 람다식을 인터페이스형 변수에 대입
        Lambda ld = s -> System.out.println(s);

        // 그 변수를 사용해 람다식 구현부 호출
        ld.showString("Hello lambda"); // Hello lambda

        // 메소드 매개변수로 람다식 대입 변수 전달
        showMyString(ld);     // 안녕 람다?

    }

    // lambda 인터페이스형 객체를 매개변수로 받는 함수
    public static void showMyString(Lambda ld) {
        ld.showString("안녕 람다?");
    }
}

예제 ③

반환 값에 람다식을 구현해서 인터페이스 객체를 생성하고
람다식으로 구현한 메소드를 호출해 보는 예제

package j200213;

@FunctionalInterface
interface Return {
    int plus(int x, int y);
}

public class LamReturn {

    public static void main(String[] args) {

        // returnRT() 메소드로 Return 객체 반환, rt 변수 초기화
        Return rt = returnRT();

        // rt 객체로 메소드 호출 및 결과 저장
        int result = rt.plus(5, 4);

        // 결과 출력
        System.out.println(result);    // 9
    }

    // Return 인터페이스 객체 반환 메소드
    public static Return returnRT() {
        /*
        Return 객체 생성 후 객체 반환
        Return rt = (x, y) -> x + y;
        return rt;
        */
        // 반환 값에 바로 람다식 구현
        return (x, y) -> x + y;
    }
}

자바에서 함수형 프로그래밍시 사용할 수 있는 람다식에 대해 살펴보았습니다.

꼭 함수형 프로그래밍이 아니더라도 간략한 표현식 덕분에

메소드가 하나인 인터페이스를 구현할 때는 편리하게 사용할 수 있을 것 같습니다.

또한 람다식은 익명 함수로 변수처럼 사용할 수 있기 때문에

변수에 람다식 구현부를 대입하는 것과 그것을 매개변수로 전달하는 것,
마지막으로 반환 값에 람다식을 직접 구현하는 형식에 대해서는 알아둘 필요가 있겠습니다.