[Java] Lambda - Using Lambda

반응형

이번 글에서는 lambda에 대해 조금 더 자세히 알아보도록 하겠습니다.

1. Using Lambda

이전 글의 예제를 다시 한번 살펴보겠습니다.

1-1) function type

이전글에서 Greeter의 greet 메서드에 특정 '기능'을 전달하기위한 방법에는 다음과 같이 2가지 방법이 존재했습니다.

첫 번째는 Interface를 생성하고, 해당 Interface를 구현한 클래스의 인스턴스를 전달하는 방법. 두 번째는 lambda 식으로 작성한 action을 전달하는 방법.

이때 lambda 식은 다음과 같이 작성할 수 있었습니다.

aBlockOfCode = () -> System.out.println("Hello World!");

그렇다면 위의 경우에 aBlockOfCode의 변수 Type은 무엇이될까요? 😅

이전 글에 설명드렸던 것 처럼, lambda 식으로 작성한 '기능'은 마치 변수처럼 사용할 수 있으므로.. 이를 저장할 수 있는 Type이 존재해야 될텐데 말이죠.. 😅

FunctionType<void,void> aBlockOfCode = () -> System.out.println("Hello World!");

위와 같은 모양으로..?

1-2) interface type

하지만 아쉽게도 java8의 개발자들은 function type을 새로 생성해 사용하지 않고, 기존 interface를 사용해 interface type으로 lambda 를 사용하기로 결정했습니다.

따라서 lambda 식을 사용하기 위해선 이를 담을 interface를 생성해야 합니다.

이때 lambda interface의 abstract method는 반드시 1개만 존재해야 하며, 해당 method의 return type과 input arguments를 작성한 lambda식과 일치시켜야 합니다.

// interface type
interface MyLambda {
    void foo( );
}

추가적으로 lambda interface에 작성한 함수는 단순히 lambda를 담기위한 껍데기에 불과하므로, 굳이 의미있는 함수명으로 작성할 필요는 없습니다.

예를 들어 input arguments가 존재하지 않고, return type이 void인 모든 labmda 식은 MyLambda Interface를 interface type으로 사용할 수 있으므로, foo라는 함수명은 더이상 의미를 가지지 않습니다.

MyLambda aBlockOfCode = () -> System.out.println("Hello World!");

결론적으로 interface type을 사용하면 위와 같이 lambda 식을 작성할 수 있습니다.

추가 예제는 다음과 같습니다.

// lambda
MyAdd addFunction = (int a, int b) -> a + b;

// interface type
interface MyAdd {
    int add(int a, int b);
}

2. Interface

여기까지 글을 읽으셨다면, 문득 스치는 생각이 있을 겁니다. 😅

어라? lambda interface의 모양이 이전의 greeting interface와 일치하네..? 그럼 lambda interface를 생성하지 말고, 이전에 작성한 greeting interface를 사용해도 되나..?

// for lambda
interface MyLambda {
    void foo( );
}

// for class
interface Greeting {
    void greet( );
}

네, 맞습니다. 사용할 수 있습니다. 😎

lambda 식의 interface type과 동일한 interface가 이미 정의되어 있을 경우, 해당 interface를 사용해 lambda식의 type을 정의하는데 사용할 수 있습니다.

이는 lambda 의 interface type은 단순히 lambda 식을 담기 위한 껍데기 역할만 하기 때문입니다.

input과 return type이 일치하고, 1개의 abstract method만 소유한 interface는 모두 lambda interface에 사용될 수 있는 조건을 갖추게 됩니다. 이를 java8에서는 '@FunctionalInterface'라고 합니다.

3. Lambda vs Interface Implementation

또 한가지 궁금한점이 있습니다. 😅 lambda도 결국에 interface의 method를 구현하는 것인데.. interface를 구현한 class를 사용하는 것 과는 무엇이 다른 것 일까요??

// instance
Greeter greeter = new Greeter();

// lambda
Greeting myLambdaGreeting = () -> System.out.println("Hello World!");
greeter.greet(myLambdaGreeting);

// inferface implementation
Greeting helloWorldGreeting = new HelloWorldGreeting();
greeter.greet(helloWorldGreeting);

위의 소스를 실행시켜보면 물론.. 결과값은 동일합니다.

다른점은 다음과 같습니다.

• interface implementation은 class instance를 생성해 작업을 수행합니다.

• 반면, lambda 는 class instance를 생성하지 '않고' 단순히 interface의 method를 calling 하는 방식으로 작업을 수행합니다.

따라서 사용자의 입장에서는 instance를 생성하는 것과 동일하게 동작하는 것으로 보이지만, 내부적으로 lambda 식으로 작성한 function은 class instance를 생성하지 않습니다.

익명 클래스(anonymous class)를 사용해 interface를 구현해도, 동일하게 class instance를 생성해 작업을 수행합니다. lambda식과 익명 클래스를 혼동하지 말아야 합니다. 😅

// instance
Greeter greeter = new Greeter();

// anonymous class
greeter.greet(new Greeting() {
    @Override
    public void perform() {
        System.out.println("Hello World!");
    }
});

추천서적

 

이것이 자바다:신용권의 Java 프로그래밍 정복

COUPANG

www.coupang.com

파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음


반응형

댓글

Designed by JB FACTORY