무지를 아는 것이 곧 앎의 시작

Java

표준 함수형 인터페이스

Alex96 2022. 3. 8. 19:47

이펙티브 자바의 아이템44. '표준 함수형 인터페이스를 사용하라' 부분을 읽고 정리하는 포스팅.✍️

아이템44 표준 함수형 인터페이스 정리

함수형 인터페이스란?

오직 하나의 추상 메소드만 저장하는 인터페이스. 필드 메소드를 파라미터화 할 수 있음.

많은 디폴트 메소드가 있더라도 추상 메소드가 오직 하나면 함수형 인터페이스다.

@FunctionalInterface를 붙이지 않아도 추상 메서드가 한개면 함수형 인터페이스이다.

ex)

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);

    // ...
}

표준 함수형 인터페이스를 사용하라.

꼭 필요한게 아니라면, 굳이 함수형 인터페이스를 정의하지 말자.
필요한 용도에 맞는 게 있다면, 직접 구현하지 말고 표준 함수형 인터페이스를 활용하라

자바의 표준 함수형 인터페이스

(5가지 기본 함수형 인터페이스 + 파생 함수형 인터페이스)


Consumer

메서드: accept

시그니처: (T) -> void

파생된 함수형 인터페이스 정리

인터페이스 시그니처 메서드
BiConsumer (T, U) -> void accept
IntConsumer (int) -> void accept
LongConsumer (long) -> void accept
DoubleConsumer (double) -> void accept
ObjIntConsumer (T, int) -> void accept
ObjLongConsumer (T, long) -> void accept
ObjDoubleConsumer (T, double) -> void accept

Supplier

메서드: get

시그니처: () -> R

파생된 함수형 인터페이스 정리

인터페이스 시그니처 메서드
BooleanSupplier void -> boolean getAsBoolean
IntConsumer void -> int getAsInt
LongConsumer void -> long getAsLong
DoubleConsumer void -> double getAsDouble

Operator 계열

메서드: apply

함수형 인터페이스 정리

인터페이스 시그니처 메서드
UnaryOperatior (T) -> T apply
BinaryOperator (T, T) -> T apply
IntUnaryOperatior (int) -> int applyAsInt
LongUnaryOperatior (long) -> long applyAsLong
DoubleUnaryOperatior (double) -> double applyAsDouble
IntBinaryOperatior (int, int) -> int applyAsInt
LongBinaryOperatior (long, long) -> long applyAsLong
DoubleBinaryOperatior (double, double) -> double applyAsDouble

Predicate계열

메서드: test

시그니처: (T) -> boolean

함수형 인터페이스 정리

인터페이스 시그니처 메서드
BiPredicate (T, U) -> boolean test
IntPredicate (int) -> boolean test
LongPredicate (long) -> boolean test
DoublePredicate (double) -> boolean test

Function계열

메서드: apply

시그니처: (T) -> R

파생된 함수형 인터페이스 정리

인터페이스 시그니처 메서드
BiFunction (T, U) -> R apply
IntFunction (int) -> R apply
LongFunction (long) -> R apply
DoubleFunction (double) -> R apply
ToIntFunction (T) -> int applyAsInt
ToLongFunction (T) -> long applyAsLong
ToDoubleFunction (T) -> double applyAsDouble
{T}To{R}Function (T) -> R applyAs{R}
To{R}BiFunction (T, U) -> R applyAs{R}

참고: 모던 자바 인 액션


주의할 점

  • 표준 함수형 인터페이스는 총 43가지로 다 외울 필요는 없다. 규칙성도 모호함.
  • 표준 함수형 인터페이스는 주로 기본타입형 특화로 지원하는데, 박싱된 기본타입을 넣어서 사용하지 말것. 계산량이 많을 경우 성능이 처참히 느려진다.
  • @FunctionalInterface를 쓰는 이유는 @Override를 붙이는 이유와 비슷하다. 이게 함수형 인터페이스라고 나타내기 위함과 동시에 추상 메서드를 오직 하나만 가지도록 컴파일러가 인식하게 한다.
    ex)

추상 메서드 두 개 선언시 컴파일 에러

  • 직접 만든 함수형 인터페이스에는 반드시 @FunctionalInterface를 붙여서 사용할 것.
  • 함수형 인터페이스를 같은 위치의 인수로 받는 메서드들을 다중 정의(오버로드)하면 안된다. 클라이언트에게 모호함을 안겨줄 뿐더러 인터페이스의 시그니처가 같으면 람다로 인수를 넘겨줄 수도 없다.
public class Test {

    public void test(TestInterface t) {
        t.test1();
    }

    public void test(TestInterface2 t2) {
        t2.test2();
    }

    // 시그니처가 같아서 람다식으로 인수를 전달할 수 없고, 직접 형변환하여 인수를 넘겨줄 수 있음
}