필요한 용도에 맞는 게 있다면, 직접 구현하지 말고 표준 함수형 인터페이스를 활용하라
기본 인터페이스(java.util.function)
인터페이스 | 함수 시그니처 | 예 |
UnaryOperator<T> | T apply(T t) | String::toLowerCase |
BinaryOperator<T> | T apply(T t1, T t2) | BigInteger::add |
Predicate<T> | boolean test(T t) | Collection::isEmpty |
Function<T, R> | R apply(T t) | Arrays::asList |
Supplier<T> | T get() | Instant::now |
Consumer<T> | void accept(T t) | System.out::println |
- 기본 인터페이스는 기본 타입인 int, long, double 용으로 각 3개씩 변형이 생겨남
- 그 이름도 기본 인터페이스의 이름 앞에 해당 기본 타입이름을 붙여 지음
- 예컨대 int를 받는 Predicate는 IntPredicate가 되고 long을 받아 long을 반환하는 BinaryOperator는 LongBinaryOperator가 되는 식
- 이 변형들 중 유일하게 Function 의 변형만 매개변수화 됐다. 정확히는 반환 타입만 매개변수화 됐는데, 예를 들어 LongFunction<int[]> 은 long 인수를 받아 int[]을 반환함
- 표준 함수형 인터페이스 대부분은 기본 타입만 지원한다. 그렇다고 기본 함수형 인터페이스에 박싱된 기본 타입을 넣어 사용하지는 말자
표준 함수형 인터페이스가 아닌 직접 작성해야 하는경우
- 표준 인터페이스 중 필요한 용도에 맞는 게 없다면 직접 작성
- 매개 변수 3개 받는 Predicate 라든가 검사 예외를 던지는 경우,,
- 자주 쓰이며, 이름 자체가 용도를 명확히 설명해준다.
- 반드시 따라야 하는 규약이 있다.
- 유용한 디폴트 메서드를 제공할 수 있다.
구조적으로 똑같은 표준 함수형 인터페이스가 있더라도 직접 작성하는 경우가 있음 (예: Comparator
인터페이스)
- 이유 1 : API에서 굉장히 자주 사용되는데, 그 이름이 그 용도를 아주 훌륭히 설명해줌
- 이유 2 : 구현하는 쪽에서 반드시 지켜야 할 규약을 담고 있다.
- 이유 3 : 비교자들을 변환하고 조합해주는 유용한 디폴트 메서드들을 듬뿍 담고 있다.
주의점
- 직접 만든 함수형 인터페이스에는 항상
@FunctionalInterface
애너테이션을 사용하라.
함수형 인터페이스를 API에서 사용할 떄의 주의점
- 서로 다른 함수형 인터페이스를 같은 위치의 인수로 받는 메서드들을 다중 정의 해서는 안 된다.