형식 검사
List<Company> companiesHasCafeteria= filter(list, (Company company)-> company.hasCafeteria());
Java
복사
람다는 사용되는 콘텍스트(Context)를 이용해 람다의 형식(Type)을 추론할 수 잇는데, 어떤 콘텍스트에서 제공될꺼라 기대되는 람다 표현식의 형식을 대상 형식(Target Type) 이라 한다.
위 코드는 사내식당을 보유한 회사 목록을 필터링하는 코드인데, 위 코드가 어떤 과정으로 형식 확인을 하는지에 대해 알아보자.
람다 표현식의 형식 검사 과정
1.
람다가 사용된 콘텍스트 확인을 해야하니 filter 메소드의 정의 확인
2.
메소드의 두 번쨰 파라미터인 Predicate<Company> p가 기대하는 대상 형식(target type)을 나타낸다.
3.
Prediate<Company> p는 boolean test(T t) 라는 하나의 추상 메서드를 정의하는 함수형 인터페이스이다.
4.
test 메서드는 Company를 받아 boolean을 반환하는 함수 디스크립터를 묘사한다.
5.
filter 메서드로 전달된 인수는 이와 같은 요구사항을 만족해야 한다.
그리고 전달되는 인수인 (Company company)→ company.hasCafeteria() 는 Company → boolean의 형태를 띄고있기에 유효하며 이렇게 형식 검사는 성공적으로 완료된다.
이러한 과정들을 보면 대상 형식(target typing)이 같다면, 같은 람다 표현식을 다른 함수형 인터페이스에서도 활용할 수 있다.
Comparator<Apple> c1 = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
ToIntBiFunction<Apple, Apple> c2 = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
BiFunction<Apple, Apple, Integer> c3 = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
Java
복사
참고: void 호환 규칙
람다의 바디에 일반 표현식이 있을 경우 void를 반환하는 함수 디스크립터와 호환된다.
Predicate<String> p = s → list.add(s); //return boolean
Consumer<String> b = s → list.add(s);// return Void
위 코드에서 람다의 바디인 list.add(s)는 Consumer 콘텍스트(T→void)가 기대하는 void 대신 boolean을 반환하지만 유효하다.
형식 추론
익명클래스나 값 파라미터에 비교해서 람다식은 많은 코드 축약을 해내었지만, 여기서 좀 더 축약을 해 볼 수 있다. 자바 컴파일러는 람다 표현식이 사용된 콘텍스트(대상 형식)을 이용해 람다 표현식과 관련된 함수형 인터페이스를 추론하기 때문에 함수 디스크립터를 알 수 있다.
이말인즉슨, 컴파일러는 람다의 시그니처도 추론할 수 있다는 의미가되고 결과적으로 컴파일러는 람다 표현식의 파라미터 형식에 접근해서 람다 문법에서 이를 생략할 수 있다.
//Before
List<Company> companiesHasCafeteria= filter(list, (Company company)-> company.hasCafeteria());
//After
List<Company> companiesHasCafeteria= filter(list, company-> company.hasCafeteria());
Java
복사
참고
•
모던 자바 인 액션 - 3장 람다 표현식