[Effective Java] 아이템 43 : 람다보다는 메서드 참조를 사용하라

Loopy·2022년 9월 9일
0

이펙티브 자바

목록 보기
42/76
post-thumbnail

☁️ 메서드 참조

메서드 참조란, 함수 객체를 람다보다 간결하게 만드는 방법이다.

람다

map.merge(key, 1, (count, incr) -> count + incr);
  • merge() : 키, 값, 함수를 인자로 받으며 주어진 키가 맵 안에 아직 없다면 주어진 {키,값} 쌍을 그대로 저장하고, 키가 이미 있다면 {키, 인자로 받은 함수의 결과} 쌍을 저장

하지만, 현재 람다는 단순 두 인수의 합을 반환할뿐이기 때문에 불필요한 코드 부분(매개변수를 받는 부분)이 존재하게 된다.

메서드 참조

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

이런 경우, 자바 8부터 도입된 모든 기본 타입의 박싱 타입에서 제공하는 정적 메소드 sum()을 사용하여 메서드의 참조를 전달하면 코드가 더 간결해진다.

☁️ 메서드 참조 장점

메서드 참조로 구현한다면, 더 짧고 간결한 코드를 생성할 수 있다.
즉 람다로 구현했을때 너무 길고 복잡하다면, 람다로 작성할 코드를 새로운 메서드에 담은 다음, 람다 대신 그 메서드 참조를 사용하면 된다.

🔖 람다가 메서드 참조보다 간결한 경우
메서드와 람다가 같은 클래스에 있는 경우 람다가 더 간결하다.

service.excecute(CoshThisClassNameIsHumongous::action);
service.execute(() -> action());

☁️ 메서드 참조 유형

1. 정적 메서드 참조

Integer::parseInt
str -> Integer.parseInt(str)

2.인스턴스 메서드 참조

2-1. 한정적(bound) 인스턴스 메서드 참조

  • 수신객체(참조 대상 인스턴스)를 특정하는 참조이며, 즉 함수 객체가 받는 인수와 참조되는 메서드가 받는 인수가 같다.
Instant.now()::isAfter
Instant then = Instant.now();
t -> then.isAfter(t)

2-2. 비한정적(unbound) 인스턴스 메서드 참조

  • 수신객체를 특정하지 않는 참조이며, 함수 객체를 적용하는 시점에 수신 객체를 알려준다.
  • 주로 스트림 파이프라인에서의 매핑과 필터 함수에 쓰인다.
String::toLowerCase
str -> str.toLowerCase()

3. 클래스 생성자

TreeMap<K,V>::new
() -> new TreeMap<K,V>()

4. 배열 생성자

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

즉 함수형 인터페이스를 위한 제네릭 함수 타입은 메서드 참조 표현식으로는 구현할 수 있지만, 람다식으로는 불가능하다.

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

profile
개인용으로 공부하는 공간입니다. 잘못된 부분은 피드백 부탁드립니다!

0개의 댓글