728x90
함수형 인터페이스(Functional Interface)?
- 하나의 추상 메서드만 존재하는 인터페이스
- 람다 표현식에 사용할 수 있는 인터페이스
- 인터페이스 범위가 확장됨에 따라 여러 메서드가 정의되어 있을 수 있지만, 오직 하나의 추상 메서드만 존재한다면 함수형 인터페이스이다.
기본 형태
@FunctionalInterface
public interface Consumer<T> {
void accept(T var1);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (t) -> {
this.accept(t);
after.accept(t);
};
}
}
@FunctionalInterface 어노테이션은 생략이 가능하다. 다만, 이를 명시하여 함수형 인터페이스임을 명확하게 할 수 있고, 개발자가 메서드를 추가하게 되면 컴파일 에러로 이를 방지할 수 있다.
함수형 인터페이스로는 무엇이 있는가?
- Runnable, Comparator, RowMapper(Spring Framework) 등
- 인터페이스에 @FunctionalInterface가 붙어 있는 라이브러리들
람다 표현식과는 무슨 관계인가?
- 람다식을 사용하기 위해서는 인터페이스에 public 메서드 하나만 있어야 한다. 따라서, 함수형 인터페이스 규칙을 따르는 인터페이스는 람다식을 활용할 수 있는 인터페이스이다.
- 이런 인터페이스는 람다식을 해당 메서드의 파라미터와 형식에 맞는지 검사 후 맞으면 컴파일하며, 명세가 다를 경우 컴파일 에러를 발생시킨다.
- 설령 Java8 이전에 만들어진 인터페이스라고 하더라도 오직 하나의 추상 메서드를 갖는 인터페이스라면 람다식을 활용할 수 있다.
java.util.function을 통해 알아보는 함수형 인터페이스
- 아래 인터페이스들은 Java8부터 나오기 시작한 라이브러리, 프레임워크에 적극적으로 활용되고 있기 때문에 각 유형에 대해 숙지하고 있는 것이 좋다.
- 기본 제공하는 함수형 인터페이스는 추가 작업이 필요 없다.
- 기본 인터페이스가 프로젝트의 명명 규칙과 맞지 않을 때는 사전에 함수형 인터페이스를 정의하고 가는 방법도 고려하는 것이 좋다.
Consumer<T>
void accept(T t)
파라미터를 전달해 처리하고, 리턴 받지 않을 경우 사용
Function<T, R>
R apply(T, t)
전달할 파라미터를 다른 값으로 변환/매핑하여 리턴할 때 사용
Predicate<T>
boolean test(T t)
파라미터에 대해 True/False를 리턴할 때(필터링, 검증) 사용
Supplier<T>
T get()
파라미터 없이 리턴 값만 있는 경우에 사용
Operator 인터페이스
- 앞서 언급된 4개 인터페이스 제외하고도 Operator 인터페이스도 존재한다.
- Operator 인터페이스는 모두 Function의 하위 인터페이스이며, Function의 apply 메서드를 사용한다. 따라서, Operator 인터페이스에서 추가되는 함수형 메서드는 없다.
- 연산을 몇 개 가지냐에 따라 인터페이스는 Unary/Binary 계열로 분리된다.
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
static <T> UnaryOperator<T> identity() {
return (t) -> {
return t;
};
}
}
@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T, T, T> {
static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> {
return comparator.compare(a, b) <= 0 ? a : b;
};
}
static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> {
return comparator.compare(a, b) >= 0 ? a : b;
};
}
}
java.util.function의 기본 활용 예시
public class FunctionExample {
public static int executeFunction(String context, Function<String, Integer> function) {
// Function은 가장 대표적인 Functional Interface
// T, R
// T : Parameter
// R : Return
return function.apply(context);
}
public static void main(String[] args) {
FunctionExample.executeFunction("Hello! Lambda & Functional Interface",
(String context) -> context.length());
}
}
728x90
'Programming Language > Java' 카테고리의 다른 글
Java의 Stream에서 parallelStream은 stream보다 항상 빠를까? (1) | 2021.07.18 |
---|---|
JAVA에서 람다식(Lambda Expression)에 대해 정리해보기 (0) | 2021.05.02 |
자바(Java)에서의 싱글톤(Singleton) 패턴에 대해 알아보자 (1) | 2020.12.13 |
자바(Java)와 메모리(Static, Stack, Heap)에 대한 정리 (0) | 2020.10.31 |