아이템 43: 람다보다는 메서드 참조를 사용하라
람다가 익명 클래스보다 나은 점 중에서 가장 큰 특징은 간결함
button .addActionListener (new ActionListener () {
@ Override public void actionPerformed (ActionEvent e ) {
System .out .println ("Button was clicked using anonymous class!" );
}
});
button .addActionListener (e -> System .out .println ("Button was clicked using lambda!" ));
그런데 자바에는 함수 객체를 심지어 람다보다도 간결하게 만드는 방법이 있으니 고거시 메서드 참조(method reference)
다음 코드는 임의의 키와 Integer 값의 매핑을 관리하는 프로그램의 일부
map .merge (key , 1 , (count , incr ) -> count + incr );
키가 만약 맵에 존재하지 않는다면 1을 Put하고 존재한다면 존재하는 value를 증가시키는 코드이다.
깔끔해 보이는 코드지만 아직도 거추장스러운 부분이 남아 있다.
매개변수인 count 와 incr은 크게 하는 일 없이 공간을 꽤 차지한다.
람다 대신 메서드 참조를 전달하면 똑같은 결과를 더 보기 좋게 얻을 수 있다.
map .merge (key , 1 , Integer ::sum );
훨씬 깔끔해졌다.
매개변수 코드들이 제거된 것을 확인할 수 있음
메서드 참조는 매개변수를 제거하기에 매개변수 수가 늘어날수록 메서드 참조로 제거할 수 있는 코드 양도 늘어난다.
IDE들은 대체로 람다를 메서드 참조로 대체할 수 있는 경우 이를 추천한다.
IDE의 권고를 따르는 것이 보통은 이득이지만, 항상 그런 것은 아니다.
때론 람다가 메서드 참조보다 간결할 때가 있다.
예로 람다를 사용하는 메서드와 람다의 대상이 되는 메서드가 같은 클래스에 위치하는 경우, 메서드 참조보다 람다가 간결한 경우가 많다.
service .execute (GoshThisClassNameIsHumongous ::action );
같은 클래스에 있는 메서드 참조 대신 람다를 사용한 예시
service .execute (() -> action ());
위와 같은 경우 메서드 참조를 사용한 코드는 더 짧지도 명확하지도 않다.
따라서 람다 쪽이 낫다.
또 메서드 참조는 매개변수 관련 코드를 제거하는데 매개변수의 이름 자체가 좋은 가이드가 될 경우 역시 메서드 참조보다 람다쪽이 좋은 경우로 볼 수 있다.
메서드 참조의 유형은 다섯가지
가장 흔한 유형은 정적 메서드를 가리키는 메서드 참조다.
...
return reservationRepository .findAll ().stream ()
.map (ReservationResponse ::from ) //from은 정적 메서드
.toList (); .
그리고 인스턴스 메서드를 참조하는 유형이 두가지 있다.
그 중 하나는 수신 객체를 특정하는 한정적 인스턴스 메서드 참조이고 다른 하나는 수신 객체를 특정하지 않는 비 한정적 인스턴스 메서드 참조이다.
//수신 객체가 한정된다 (Instance.now()가 메서드 참조 결과를 수신)
Instance .now ()::isAfter
//수신 객체가 한정되지 않음
String ::toLowerCase
마지막으로, 클래스 생성자를 가리키는 메서드 참조와 배열 생성자를 가리키는 메서드 참조가 있다.
5가지 유형을 가지는 메서드 참조는 람다의 간단명료한 대안이 될 수 있다.
메서드 참조 쪽이 짧고 명확하다면 메서드 참조를 쓰고, 그렇지 않을 때만 람다를 사용하라.