가자공부하러!

모던자바인액션(CH3) - 람다 표현식 본문

공부/Java

모던자바인액션(CH3) - 람다 표현식

오피스엑소더스 2020. 4. 20. 19:44

목차

요약 및 결론
책 내용


요약 및 결론

람다와 메서드 참조는 편하고 좋기 떄문에 잘 읽고 잘 메모해뒀다가 잘 익혀서 쓰도록


책 내용

**String, Integer 등을 보통 나는 타입이라고 말하는데 책에서는 형식으로 표현함
**(파라미터) -> {바디}

  1. 람다란 무엇인가?

    • 메서드로 전달할 수 있는 익명 함수를 단순화한 것

    • 특징

      • 익명 : 이름이 없고 구현해야 할 코드가 적음
      • 함수 : 특정 클래스에 종속되지 않지만 메서드처럼 파라미터 리스트, 바디, 리턴타입, 예외리스트를 포함한다.
      • 전달 : 람다 표현식을 메서드 인수로 전달하거나 변수로 저장할 수 있다.
      • 간결성
    • 구성

      
      //람다 파라미터, 화살표, 람다 바디
      (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
      
      
      //헷갈렸던 문법
      (Integer i) -> {return "Mario";}     //O
      (Integer i) -> {"Mario"}            //X
      (Integer i) -> return "Mario";        //X
      (Integer i) -> "Mario"                //O
      
  2. 어디에 어떻게 람다를 사용하는가?

    • 함수형 인터페이스라는 문맥에서 람다 표현식을 사용할 수 있다.
    • 함수 디스크립터 : 람다 표현식의 시그니처를 서술하는 메서드
    • 왜 함수형 인터페이스를 인수로 받는 메서드에만 람다 표현식을 사용할 수 있을까?
      • 20장, 21장에서 다룰 예정
  3. 실행 어라운드 패턴

    • 준비코드와 마무리코드가 작업을 감싸고 있는 형태
  4. 함수형 인터페이스, 형식 추론

    • 함수형 인터페이스 : 정확히 하나의 추상 메서드만 갖는 인터페이스
      • @FuntionalInterface 어노테이션을 붙인 인터페이스가 함수형 인터페이스가 아니라면 컴파일에러 발생
      • Predicate, Consumer, Function, Supplier, UnaryOperator, BinaryOperator, BiPredicate, BiConsumer, BiFunction
        • 각 함수형 인터페이스와 연관된 기본형 특화 인터페이스들이 있다
      • 예외, 람다, 함수형 인터페이스의 관계
        • 함수형 인터페이스는 확인된 예외를 던지는 동작을 허용하지 않는다.
        • 예외를 던지는 람다 표현식을 만드려면?
          • 확인된 예외를 선언하는 함수형 인터페이스를 직접 선언
          • 람다를 try-catch 블록으로 감싸기
    • 형식 검사, 형식 추론, 제약
      • 람다 표현식 자체에는 어떤 정보가 포함되어있는지 알 수 없기 때문에 람다의 실제 형식을 파악하고 있어야 한다.
      • 형식(타입) 검사 : 람다 표현식에 사용된 대상 형식과 디스크립터를 검사해서 유효한 람다 표현식인지 확인하는 절차
        • 대상형식 : 어떤 콘텍스트에서 기대되는 람다 표현식의 형식(Predicate, Consumer 등)
      • 형식(타입) 추론 : 자바 컴파일러는 람다 파라미터 타입을 추론할 수 있기때문에 타입을 명시하지 않아도 된다.
      • 지역변수 사용과 제약
        • 명시적으로 final로 선언되어 있거나 실질적으로 final처럼 사용되는 지역변수만 사용할 수 있다
        • 지역변수는 스택에 위치하고 인스턴스 변수는 힙에 저장되는데 람다가 스레드에서 실행된다면 변수를 할당한 스레드가 사라져서 변수 할당이 해제됐는데도 해당 변수에 접근을 시도할 수 있기 때문에 자유 지역변수의 복사본을 제공한다. 따라서 복사본 값이 바뀌지 않아야 하므로 final 또는 final처럼 사용되는 변수만 사용할 수 있는 것
  5. 메서드 참조

    • 특정 람다 표현식을 축약한 것

      //이전 람다
      inventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));
      //메서드 참조
      inventory.sort(comparing(Apple:getWeight));
    • 하나의 메서드를 참조하는 람다를 편리하게 표현할 수 있는 문법

      //람다 표현식을 메서드 참조로 바꾸는 방법 1
      (args) -> ClassName.staticMethod(args)
      ClassName::staticMethod
      //람다 표현식을 메서드 참조로 바꾸는 방법 2
      (arg0, rest) -> arg0.instanceMethod(rest)    //arg0은 ClassName형식
      ClassName::instanceMethod
      //람다 표현식을 메서드 참조로 바꾸는 방법 3
      (args) -> expr.instanceMethod(args)
      expr::instanceMethod
    • 생성자도 메서드 참조 기능 사용 가능 ex) Apple::new

  6. 유용한 메서드

    • Comparator

      Comparator<Apple> c = Comparator.comparing(Apple::getWeight);
      inventory.sort(comparing(Apple::getWeight).reversed().thenComparing(Apple::getCountry));
    • Predicate

      Predicate redAndHeavy = redApple.and(apple -> apple.getWeight() > 150);
      Predicate<Apple> redAndHeavyOrGreen = redApple.and(apple -> apple.getWeight() > 150).or(apple -> GREEN.equals(a.getColor()));
    • Function : andThen, compose

      //andThen == g(f(x))
      Function<Integer, Integer> f = x -> x + 1;
      Function<Integer, Integer> g = x -> x * 2;
      Function<Integer, Integer> h = f.andThen(g);
      int result = h.apply(1); //result == 4
      //compose == f(g(x))
      Function<Integer, Integer> f = x -> x + 1;
      Function<Integer, Integer> g = x -> x * 2;
      Function<Integer, Integer> h = f.compose(g);
      int result = h.apply(1); //result == 3

** 생성자참조 어떤 원리로 이루어지는지 공부해오기

Comments