함수형 인터페이스
추상 메서드가 하나만 존재하는 인터페이스이며, FunctionalInterface 어노테이션이 사용된 것
만약, 추상 메서드가 두 개 존재한다면 Multiple non-overriding abstract methods found 에러가 뜬다.
커스텀 예시
함수형 인터페이스 생성
@FunctionalInterface
public interface FuncInterface<T> {
T uniqueMethod();
default void printDefault() {
System.out.println("print default!");
}
}
default, static 메서드의 개수는 무관하고, 추상 메서드만 하나 존재하면 된다.
함수형 인터페이스 사용
public class FuncInterfaceTest {
public static void main(String[] args) {
FuncInterface<String> funcInterface = () -> "Hello World";
String result = funcInterface.uniqueMethod();
System.out.println("result = " + result);
}
의문이 들었다. FuncInterface 의 구현체가 없고, uniqueMethod 메서드를 구현한 적이 없는데 어떻게 실행된 걸까?
FuncInterface<String> funcInterface = () -> "Hello World";
위 코드에서 uniqueMethod 메서드를 구현한 것이다. 함수형 인터페이스는 하나의 추상 메서드만 가져야 한다고 했다.
그러므로 하나의 변수를 선언할 때 람다식으로 구현이 가능한 것이다.
두 개의 추상메서드라면 어떤 메서드에 대한 구현인지 컴파일러는 모를 것이다.
또 의문이 든다. 그렇다면 그동안 왜 함수형 인터페이스를 구현해서 사용하지 않았을까?
사실 우리는 Stream 의 메서드를 사용할 때마다 Java에서 제공하는 함수형 인터페이스를 매번 구현해서 사용하고 있다.
Java에 존재하는 함수형 인터페이스
함수형 인터페이스
|
Descripter
|
Method
|
Predicate
|
T -> boolean
|
boolean test(T t)
|
Consumer
|
T -> void
|
void accept(T t)
|
Supplier
|
() -> T
|
T get()
|
Function<T, R>
|
T -> R
|
R apply(T t)
|
Comparator
|
(T, T) -> int
|
int compare(T o1, T o2)
|
함수형 인터페이스 구현 예시
// StreamTest.java
Arrays.stream(stringArray)
.filter(string -> string.equals("a"));
흔히 stream 의 메서드를 이런 식으로 사용한다.
// Stream.java
public interface Stream<T> extends BaseStream<T, Stream<T>> {
Stream<T> filter(Predicate<? super T> predicate);
}
stream 메서드는 Predicate 함수형 인터페이스를 매개변수로 받고 있다.
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
Predicate 는 추상메서드인 test 가 존재하고, boolean 타입으로 반환한다.
.filter(string -> string.equals("a"));
filter 메서드를 사용할 때처럼 우리는 매번 Predicate를 비롯한 함수형 인터페이스의 메서드를 구현해서 사용하고 있는 것이다.

Predicate 함수형 인터페이스를 익명 함수로 구현했다.
함수형 인터페이스 별 사용 예시
// Consumer
Arrays.stream(stringArray)
.forEach(string -> System.out.println(string));
// Supplier
// Gets a result. (객체 등 함수가 아닌 결과를 반환한다.)
Order order = orderQueryService.getOrderByOrderNo(kisOrderId)
.orElseThrow(() -> new RuntimeException("[주문 내역 조회 실패] 주문 정보 존재하지 않음 : " + kisOrderId));
// Function
// Returns: the function result (함수의 결과를 반환한다.)
@Getter
@AllArgsConstructor
public enum OrderDvsnCode {
SELL("01", "S"),
BUY("02", "B");
private String code;
private String value;
private static Map<String, OrderDvsnCode> map = Arrays.stream(OrderDvsnCode.values())
.collect(Collectors.toMap(code -> code.getCode(), e -> e));
public static OrderDvsnCode find(String code) {
return map.get(code);
}
}
참고 자료
'Java' 카테고리의 다른 글
Java static Map 초기화 한번만 하기 (1) | 2023.12.15 |
---|---|
가비지 컬렉터(Garbage Collector) 의 종류 (0) | 2023.11.29 |
소나 큐브 사용법(Sonar Qube) (0) | 2023.11.29 |
Lombok (1) | 2023.11.28 |
Java Optional (0) | 2023.09.29 |