메서드 참조란, 함수 객체를 람다보다 간결하게 만드는 방법이다.
map.merge(key, 1, (count, incr) -> count + incr);
merge()
: 키, 값, 함수를 인자로 받으며 주어진 키가 맵 안에 아직 없다면 주어진 {키,값}
쌍을 그대로 저장하고, 키가 이미 있다면 {키, 인자로 받은 함수의 결과}
쌍을 저장하지만, 현재 람다는 단순 두 인수의 합을 반환할뿐이기 때문에 불필요한 코드 부분(매개변수를 받는 부분)이 존재하게 된다.
map.merge(key, 1, Integer::sum);
이런 경우, 자바 8부터 도입된 모든 기본 타입의 박싱 타입에서 제공하는 정적 메소드 sum()
을 사용하여 메서드의 참조를 전달하면 코드가 더 간결해진다.
메서드 참조로 구현한다면, 더 짧고 간결한 코드를 생성할 수 있다.
즉 람다로 구현했을때 너무 길고 복잡하다면, 람다로 작성할 코드를 새로운 메서드에 담은 다음, 람다 대신 그 메서드 참조를 사용하면 된다.
🔖 람다가 메서드 참조보다 간결한 경우
메서드와 람다가 같은 클래스에 있는 경우 람다가 더 간결하다.service.excecute(CoshThisClassNameIsHumongous::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]
보통, 람다로 할 수 없는 일이라면 메서드 참조로도 할 수 없다.
하지만, 제네릭 함수 타입(genereic 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
즉 함수형 인터페이스를 위한 제네릭 함수 타입은 메서드 참조 표현식으로는 구현할 수 있지만, 람다식으로는 불가능하다.
📚 핵심 정리
메서드 참조는 람다의 간다명료한 대안이 될 수 있다. 메서드 참조 쪽이 짧고 명확하다면 메서드 참조를 쓰고, 그렇지 않을 때만 람다를 사용하라.