함수형 인터페이스 ?
함수형 인터페이스란 1개의 추상 메소드를 갖는 인터페이스이다.여러개의 디폴트 메서드가 있더라도 추상 메소드가 1개라면 함수형 인터페이스가 된다.JAVA8 부터 인터페이스는 기본 구현체를 포함한 디폴트 메소드를 포함할 수 있으며,
자바의 람다 표현식은 함수형 인터페이스로만 사용 가능하다.
Functional Interface 생성
@FunctionalInterface
interface CustomInterface<T> {
// abstract method 오직 하나
T myCall();
// default method 는 존재해도 상관없음
default void printDefault() {
System.out.println("Hello Default");
}
// static method 는 존재해도 상관없음
static void printStatic() {
System.out.println("Hello Static");
}
}
위 인터페이스는 추상메소드를 1개 가지고 있기 때문에 함수형 인터페이스가 된다.
default method, static method 를 넣어도 문제가 되지 않는다.
@FunctionalInterface 를 선언하면 함수형인터페이스 형식에 맞지 않을 때 다음과 같은 에러를 띄운다.
Multiple non-overriding abstract methods found in interface com.practice.notepad.CustomFunctionalInterface
함수형 인터페이스를 이용한 람다식 표현
CustomInterface<String> customInterface = () -> "Hello Custom";
// abstract method
String s = customInterface.myCall();
System.out.println(s);
// default method
customInterface.printDefault();
// static method
CustomFunctionalInterface.printStatic();
String 타입을 래핑했기 때문에 myCall() 은 String 타입을 리턴한다.
그 외 default method, static method도 그대로 사용할 수 있다.
위 코드를 실행한 결과는 아래와 같다.
Hello Custom
Hello Default
Hello Static
JAVA8에서 기본적으로 제공하는 Functional Interface
함수형 인터페이스 | 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) |
Runnable | () -> void | void run() |
Callable | () -> T | V call() |
추가로 T와 R에 대해서 따로 찾아보았다.
T - 함수에 대한 입력 유형
R - 함수 결과의 유형
Predicate
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
Predicate는 인자 1개를 받아서 boolean 타입을 리턴한다.
람다식으로는 T -> boolean 으로 표현한다.
Consumer
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
Counsumer는 인자 1개를 받고 리턴이 없는 void 타입이다.
말그대로 소비하는 놈인 듯하다.
람다식으로는 T -> void 으로 표현한다.
Supplier
@FunctionalInterface
public interface Supplier<T> {
T get();
}
Supplier는 아무런 인자값을 받지 않고 T타입의 객체를 리턴한다.
람다식으로는 () -> T 으로 표현한다.
위에 Consumer와 마찬가지로 이 친구 역시 공급자다운 이름값을 하는듯
Function<T, R>
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
Function 은 T타입 인자를 받아서 R타입을 리턴한다.
람다식으로는 T -> R 으로 표현한다.
T와 R은 같은 타입을 사용할 수도 있다.
Comparator
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
Comparator은 2개의 T타입 인자를 받아서 int 타입을 리턴한다.
람다식으로는 (T, T) -> int 으로 표현한다.
Runnable
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Runable은 아무런 객체를 받지 않고 리턴도 하지 않는다.람다식으로 () -> void 으로 표현한다.
말그대로 실행만하는 친구인 듯하다.
Callable
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
Callable은 인자값을 받지 않고 T타입의 객체를 리턴한다.
람다식으로는 () -> T 으로 표현한다.
이 친구 역시 말그대로 어디선가 호출하면 튀어나가는 그런 모습인듯
Supplier 와 동일하게 인자값을 받지 않고 특정 타입을 리턴한다.
둘의 차이는 사실상 없다고 생각하면 된다.
단지 Callable 은 Runnable과 함께 병렬 처리를 위해 등장했던 개념으로서 ExecutorService.submit 같은 함수는 인자로 Callable 을 받는다.
람다식에 대한 내용은 위에 블로그한것 외에도 많은 것들이 있다.
Bi 인터페이스 라든지, 기본형 특화 인터페이스라든지 등등 상황에 따라서 검색하여 적절하게 사용하는 것도 능력이 될 수 있다고 생각한다.
'Backend > JAVA' 카테고리의 다른 글
[JAVA] Stream (스트림) (0) | 2022.06.20 |
---|---|
[JAVA] Default method (디폴트 메소드) (0) | 2022.05.09 |
[JAVA] Lambda Expression(람다 표현식) (0) | 2022.01.27 |
[JAVA] JAVA 8 의 주요 변경사항 (0) | 2022.01.27 |
[JAVA] lombok 롬복이란? (0) | 2022.01.22 |