# 아이템 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::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]|

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

```java
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` 와 같다.
- 함수형 인터페이스를 위한 제네릭 함수 타입은 메서드 참조 표현식으로는 구현할 수 있지만, 람다식으로는 불가능하다. 제네릭은 람다식이라는 문법이 존재하지 않기 때문이다.

## 핵심 정리

- 메서드 참조는 람다의 간단명료한 대안이 될 수 있다.
- **메서드 참조 쪽이 짧고 명확하다면 메서드 참조를 쓰고, 그렇지 않을 때만 람다를 사용하도록 한다.**