이펙티브 자바의 아이템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();
}
// 시그니처가 같아서 람다식으로 인수를 전달할 수 없고, 직접 형변환하여 인수를 넘겨줄 수 있음
}
'Java' 카테고리의 다른 글
멤버 클래스는 되도록 static으로 (2) | 2022.03.30 |
---|---|
Stream.forEach() vs for-each (0) | 2022.03.14 |
Collections.unmodifiableXX()는 방어적 복사가 아니다 (1) | 2022.03.06 |
Collection의 깊은 복사와 방어적 복사 (2) | 2022.03.05 |
추상 클래스와 인터페이스의 용도 차이 (0) | 2022.03.03 |