아이템 43. 람다보다는 메서드 참조를 사용하라

콜트·2021년 8월 30일
0
post-thumbnail

아이템 43. 람다보다는 메서드 참조를 사용하라

  • 람다가 익명 클래스보다 나은 점 중에서 가장 큰 특징은 간결함이다.
  • 자바에는 함수 객체를 람다보다도 더 간결하게 만드는 방법이 있는데, 메서드 참조(method reference)다.

메서드 참조

  • 자바 8이 되면서 Interger 클래스와 모든 기본 타입의 박싱 타입은 람다와 기능이 같은 정적 메서드들을 제공하기 시작했다.
  • 람다 대신 이 메서드의 참조를 전달하면 똑같은 결과를 더 보기 좋게 얻을 수 있다.
    • ex. Integer::sum
  • 람다로 할 수 없는 일이라면 메서드 참조로도 할 수 없다.
  • 그래도 메서드 참조를 사용하는 편이 보통은 더 짧고 간결하므로, 람다로 구현했을 때 너무 길거나 복잡하다면 메서드 참조가 좋은 대안이 될 수 있다.
    • 람다로 작성할 코드를 새로운 메서드에 담은 다음, 람다 대신 그 메서드 참조를 사용하는 식이다.
    • 메서드 참조에는 기능을 잘 드러내는 이름을 지어줄 수 있고 설명을 문서로 남길 수도 있다.

메서드와 람다가 같은 클래스에 있을 때는 람다가 메서드 참조보다 간결하다.

service.execute(GoshThisClassNameIsHumongous::action);

  • 위 코드를 메서드로 대체하면 아래와 같다.

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

  • 메서드 참조 쪽은 더 짧지도, 더 명확하지도 않다. 따라서 람다 쪽이 낫다.

메서드 참조의 유형

  • 메서드 참조의 유형은 다섯 가지이다.
    1. 정적 메서드를 가리키는 메서드 참조하는 유형
    2. 수신 객체(receiving object; 참조 대상 인스턴스)를 특정하는 한정적(bound) 인스턴스 메서드 참조.
      • 한정적 참조는 근본적으로 정적 참조와 비슷하다. 함수 객체가 받는 인수와 참조되는 메서드가 받는 인수가 똑같다.
    3. 수신 객체를 특정하지 않는 비한정적(unbound) 인스턴스 메서드 참조.
      • 비한정적 참조에서는 함수 객체를 적용하는 시점에 수신 객체를 알려준다.
      • 이를 위해 수신 객체 전달용 매개변수가 매개변수 목록의 첫 번째로 추가되며, 그 뒤로는 참조되는 메서드 선언에 정의된 매개변수들이 뒤따른다.
      • 비한정적 참조는 주로 스트림 파이프라인에서의 매핑과 필터 함수에 쓰인다.
    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]

제네릭 함수 타입(generic function type)

interface G1 {
    <E extends Exception> Object m() throws E;
}

interface G2 {
    <F extends Exception> String m() throws Exception;
}

interface G extends G1, G2 {
}
  • 람다로는 불가능하지만 메서드 참조로는 가능한 유일한 예가 제네릭 함수 타입 구현이다.
  • 함수형 인터페이스의 추상 메서드가 제네릭일 수 있듯이 함수 타입도 제네릭일 수 있다.
  • 위 코드에서 함수형 인터페이스 G를 함수 타입으로 표현하면 <F extends Exception> () -> String throws F 와 같다.
  • 함수형 인터페이스를 위한 제네릭 함수 타입은 메서드 참조 표현식으로는 구현할 수 있지만, 람다식으로는 불가능하다. 제네릭은 람다식이라는 문법이 존재하지 않기 때문이다.

핵심 정리

  • 메서드 참조는 람다의 간단명료한 대안이 될 수 있다.
  • 메서드 참조 쪽이 짧고 명확하다면 메서드 참조를 쓰고, 그렇지 않을 때만 람다를 사용하도록 한다.
profile
개발 블로그이지만 꼭 개발 이야기만 쓰라는 법은 없으니, 그냥 쓰고 싶은 내용이면 뭐든 쓰려고 합니다. 코드는 깃허브에다 작성할 수도 있으니까요.

0개의 댓글