아이템 43. 람다보다는 메소드 참조를 사용하라. - ksw6169/effective-java GitHub Wiki

메소드 참조(method reference)

메소드 참조는 함수 객체를 람다보다도 더 간결하게 만드는 방법이다. 다음 코드는 임의의 키와 Integer 값의 매핑을 관리하는 프로그램의 일부로 키가 맵 안에 없다면 키와 숫자 1을 매핑하고, 이미 있다면 기존 매핑 값을 증가시킨다.

// key가 없다면 1을, key가 이미 있다면 (key의 기존 값 + 1)을 넣어준다.
map.merge(key, 1, (count, incr) -> count + incr);

참고로 Java 8부터 추가된 Map의 merge 메소드는 (키, 값, 함수) 를 매개변수로 받아 키가 맵에 없다면 키와 값을 Map에 넣어주고, 이미 있다면 인수로 넣은 함수의 실행 결과로 덮어쓴다.

default V merge(K key, V value,
        BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
    
    V oldValue = get(key);
    V newValue = (oldValue == null) ? value :
               remappingFunction.apply(oldValue, value);
    if (newValue == null) {
        remove(key);
    } else {
        put(key, newValue);
    }
    return newValue;
}

기본 타입의 박싱 타입에서는 정적 메소드인 sum() 을 제공하는데 이를 이용해 위 코드에서 사용한 람다식((count, incr) -> count + incr) 을 메소드 참조로 대체할 수 있다.

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

추가

람다로 할 수 없는 일이라면 메소드 참조로도 할 수 없다.


람다 → 메소드 참조

람다를 메소드 참조로 대체하는 방법은 이미 있는 메소드를 활용하는 방법도 있지만, 람다식으로 작성된 코드를 메소드를 만들어 직접 대체하는 방법도 있다. 즉 람다로 작성할 코드를 새로운 메소드에 담은 다음 람다 대신 그 메소드 참조를 사용하는 식이다. 메소드 참조에는 기능을 잘 드러내는 이름을 지어줄 수 있고 설명을 문서에 남길 수도 있다.


메소드 참조로 대체하는 것이 항상 옳은 것은 아니다.

매개변수 수가 늘어날수록 메소드 참조로 제거할 수 있는 코드양도 늘어난다. 하지만 어떤 람다에서는 매개변수의 이름 자체가 프로그래머에게 좋은 가이드가 되기도 한다. 이런 람다는 길이가 더 길지만 메소드 참조보다 읽기 쉽고 유지보수도 쉬울 것이다. 때로는 람다가 메소드 참조보다 간결할 때가 있다. 주로 메소드와 람다가 같은 클래스에 있을 때 그렇다.

service.execute(GoshThisClassNameIsHumongous::action);

이를 람다로 대체하면 다음처럼 된다.

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

메소드 참조의 유형

메소드 참조의 유형은 다섯 가지다.

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

참고 자료

  • Effective Java 3/E
⚠️ **GitHub.com Fallback** ⚠️