Java/Effective Java 3E

[이펙티브자바 3판] ITEM43. 람다보다는 메서드 참조를 사용하라

잭피 2020. 12. 1. 22:20

이번장의 핵심은...

메서드 참조는 람다의 간단명료한 대안이 될 수 있다

메서드 참조 쪽이 짧고 명확하다면 메서드 참조를 쓰고, 그렇지 않을 때만 람다를 사용하라


메서드 참조

함수 객체를 람다보다 더 간결하게 만드는 방법입니다

 

메서드 참조를 사용하는 편이 보통은 더 짧고 간결하므로, 람다로 구현했을 때 너무 길거나 복잡하다면 메서드 참조가 좋은 대안입니다

 

기능을 잘 드러내는 이름을 짓거나 친절한 설명을 문서로 남길 수도 있습니다

 

IDE들은 람다를 메서드 참조로 대체하라고 권하고 있습니다

보통은 이득이지만 항상은 아닙니다

때로는 람다가 더 간결할 수 있습니다

// 메서드 참조
service.execute(GoshThisClassNameIsHumongous::action);
// lamda
service.execute(()->action());

메서드 참조가 더 짧지도, 더 명확하지도 않습니다 

람다 쪽이 더 낫습니다

 

자바 8때 Map에 추가된 merge 메서드

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

키, 값, 함수를 인수로 받습니다

map에 키가 없다면 주어진 {키:값} 쌍을 그대로 저장합니다

map에 키가 존재하면 함수를 현재 값과 주어진 값에 적용합니다 (그리고 그 결과로 값을 덮어씁니다) - {키:함수의결과}

 

깔끔해보이지만 매개변수 count와 incr은 크게 하는 일 없이 공간만 차지하고 있습니다

그냥 이 람다는 두 인수의 합을 단순히 반환해줍니다

자바 8부터 Integer 클래스(와 모든 기본의 박싱 타입)은 이 람다와 기능이 같은 정적 메서드 sum을 제공합니다

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

따라서 람다 대신 이 메서드의 참조를 전달하면 똑같은 결과를 더 보기 좋게 얻을 수 있습니다

 

매개변수 수가 늘어날 수록 메서드 참조로 제거할 수 있는 코드양도 늘어납니다

(하지만 때론 람다를 사용할 때 매개변수 이름 자체가 좋은 가이드가 될 수 있습니다

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

 

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

예외) 제네릭 함수 타입

람다로는 불가능하나 메서드 참조로는 가능한 유일한 예외입니다

함수형 인터페이스의 추상 메서드가 제네릭일 수 있듯이 함수 타입도 제네릭일 수 있습니다

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

함수형 인터페이스를 위한 제네릭 함수 타입은 메서드 참조 표현식으로 구현할 수 있지만,

람다식으로는 불가능합니다 (제네릭 람다식이라는 문법이 존재하지 않습니다)

 

 

 

이 글은 “이펙티브 자바 3판” 책 내용을 정리한 글입니다.

만약 저작권 관련 문제가 있다면 “shk3029@kakao.com”로 메일을 보내주시면, 바로 삭제하도록 하겠습니다.