Posts [이펙티브자바] 아이템43-람다보다는 메서드 참조를 사용하라
Post
Cancel

[이펙티브자바] 아이템43-람다보다는 메서드 참조를 사용하라

람다보다 메서드 참조를 사용해야 하는 이유 - 간결함

1
map.merge(key, 1, (count, incr) -> count + incr);

위 코드는 자바 8때 Map에 추가된 merge 메서드를 사용했다.

merge 메서드는 키, 값, 함수를 인수로 받으며, 주어진 키가 맵 안에 아직 없다면 주어진 {키, 값} 쌍을 그대로 저장한다.

반대로 키가 이미 있다면 (세 번재 인수로 받은) 함수를 현재 값과 주어진 값에 적용한 다음, 그 결과로 현재 값을 덮어쓴다.

즉, 맵에 {키, 함수의 결과} 쌍을 저장한다. 관련해서는 여기를 참고하자.

여기서 매개변수 count와 incr은 크게 하는 일 없이 공간을 꽤 차지한다. 사실 이 람다는 두 인수의 합을 단순히 반환할 뿐이다. 자바8이되면서 Integer 클래스(와 모든 기본 타입의 박싱 타입)는 이 람다와 기능이 같은 정적 메서드 sum을 제공하기 시작했다. 따라서 람다 대신 이 메서드의 참조를 전달하면 똑같은 결과를 더 보기 좋게 얻을 수 있다.

1
map.merge(key, 1, Integer::sum);

때로는 람다보다 메서드 참조가 더 좋을 때가 있다.

1) 어떤 람다에선 매개변수의 이름 자체가 프로그래머에게 좋은 가이드가 되기도 한다.

이런 람다는 길이는 더 길지만 메서드 참조보다 읽기 쉽고 유지보수도 쉬울 수 있다.

2) 때론 람다가 메서드 참조보다 간결할 때가 있다.

주로 메서드와 람다가 같은 클래스에 있을 때 그렇다.

예를 들어, 다음 코드가 GoshThisClassNameIshumongous 클래스 ㅇ나에 있다고 해보자.

1
service.execute(GoshThisClassNameIsHumongous::action);

이름 람다로 대체하면 아래처럼 훨씬 간결해진다.

1
service.execute(() -> action());

메서드 참조 쪽은 더 짧지도, 더 명확하지도 않다. 같은 선상에서 java.util.function 패키지가 제공하는 정적팩터리 메서드인 Function.identity()를 사용하기 보단 똑같은 기능의 람다(x -> x)를 직접 사용하는 편이 코드도 짧고 명확하다.

메서드 참조의 다섯가지 유형

1) 위에서 소개된 같은 정적 메서드를 가리키는 메서드 참조

2) 수신 객체(참조 대상 인스턴스)를 특정하는 한정적(bound) 인스턴스 메서드 참조

  • 근본적으로 정적 참조와 비슷
  • 즉, 함수 객체가 받는 인수와 참조되는 메서드가 받는 인수가 똑같음

3) 수신 객체(참조 대상 인스턴스)를 특정하지 않는 비한정적(unbound) 인스턴스 메서드 참조

  • 함수 객체를 적용하는 시점에 수신 객체를 알려줌
  • 이를 위해 수신 객체 전달용 매개변수가 매개변수 목록의 첫번째로 추가되며, 그 뒤로는 참조되는 메서드 선언에 정의된 매개변수들이 뒤따른다.
  • 주로 스트림 파이프라인에서 매핑과 필터 함수에 쓰인다.(아이템45)

4) 클래스 생성자를 가리키는 메서드 참조

5) 배열 생성자를 가리키는 메서드 참조

메서드 참조 유형같은 기능을 하는 람다
정적Integer::parseIntstr -> Integer.parseInt(str)
한정적(인스턴스)Instant.now::isAfterInstant then = Instant.now(); t -> then.isAfter(t)
비한정적(인스턴스)String::toLowerCasestr -> str.toLowerCase()
클래스 생성자TreeMap<K, V>::new() -> new TreeMap<K, V>()
배열 생성자int[]::newlen -> new int[len]

핵심 정리: 메서드 참조는 람다의 간단명료한 대안이 될 수 있다. 메서드 참조 쪽이 짧고 명확하다면 메서드 참조를 쓰고, 그렇지 않을 때만 람다를 사용하도록 한다.

This post is licensed under CC BY 4.0 by the author.

[Spring] Spring EventListener

[이펙티브자바] 아이템45-스트림은 주의해서 사용하라