기록/JAVA

[JAVA8] 람다 표현식

jeongdalma 2021. 1. 10. 00:44

람다

  •  (인자 리스트) -> {바디}
BinaryOperator <Integer> test = (a , b) -> a + b;

인자 리스트

  • 인자가 없을 때 : ()
  • 인자가 한 개 일 때 : (one) 또는 one
  • 인자가 여러 개 일 때 : (one , two)
  • 인자의 타입은 생략 가능 , 컴파일러가 추론 (infer) 하지만 명시할 수도 있다. (Integer one , Integer two)

바디

  • 화살표 오른쪽에 함수 본문을 정의한다.
  • 여러 줄인 경우에 {}를 사용해서 묶는다.
  • 한 줄인 경우에 생략 가능 , return도 생략 가능

변수 캡처 (Variable Capture)

  • 로컬 변수 캡처
    • final 이거나 effective final 인 경우에만 참조할 수 있다.
    • 그렇지 않을 경우 concurrency(동시성) 문제가 생길 수 있어서 컴파일러가 방지한다.
  • effective final
    • 이것도 역시 자바 8 부터 지원하는 기능으로 "사실상" final인 변수이다.
    • final 키워드를 사용하지 않은 변수를 익명 클래스 구현체 또는 람다에서 참조할 수 있다.
  • 람다 표현식은 익명 클래스 구현체와 달리 "쉐도윙" 하지 않는다.
    • 익명 클래스는 새로 scope(범위)를 만들지만 , 람다는 람다를 감싸고 있는 scope(범위)와 같다.
    private void run(){
        // final 없어도 참조가 가능하다.
        // final 없지만 어디에서도 이 변수를 수정하지 않는 것 (사실상 final - effective final)
        int baseNumber = 10;

        // 쉐도윙
        // Foo class -> run method -> 람다 , 익명 클래스 , 내부 클래스
        // 내부 클래스 , 익명 클래스 - 쉐도윙이 일어난다.
        // 람다 - 쉐도윙이 일어나지 않는다.

        // 람다 표현식 지역 변수 참조
        IntConsumer printInt = (i) -> {
            int baseNumber = 11;
            System.out.println(i + baseNumber);
        };
        printInt.accept(10);


        // 익명 클래스에서 지역 변수 참조
        Consumer<Integer> test2 = new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                int baseNumber = 12;
                System.out.println(baseNumber);
            }
        };

        // 내부(로컬) 클래스에서 지역 변수 참조
        class LocalClass{
            void printBaseNumber(){
                int baseNumber = 13;
                System.out.println(baseNumber);
            }
        }
    }
  • 람다 scope 안의 int baseNumber = 11;은 컴파일 에러가 난다. (쉐도윙이 일어나지 않는다.)

scope가 동일하여 동일한 변수가 2개 선언되었기 때문에

  • 람다 표현식의 scope(범위)와 메소드의 scope가 동일하다.
  • scope가 동일하기 때문에 baseNumber가 변경된다면 컴파일 에러가 발생한다. 

effective final (사실상 final)이 아니기 때문에

 

 

  • 하지만 익명 클래스와 내부 클래스는 쉐도윙이 일어난다.
    • 익명 클래스와 내부 클래스에서 선언된 baseNumber가 run 메소드의 baseNumber를 덮어 버린다.

 

 

 

더 자바, Java 8 - 인프런

자바 8에 추가된 기능들은 자바가 제공하는 API는 물론이고 스프링 같은 제 3의 라이브러리 및 프레임워크에서도 널리 사용되고 있습니다. 이 시대의 자바 개발자라면 반드시 알아야 합니다. 이

www.inflearn.com