Java에서 하나의 추상메소드가 정의된 interface를 함수형 인터페이스라 한다.
이러한 특성 때문에, 함수형 인터페이스는 메소드 참조를 통해, 혹은 람다식 정의를 통해 stream에서 사용할 수 있다.
함수형 인터페이스를 만드는 방법은, 하나의 추상메소드를 두고 클래스 정의부에 @FunctionalInterface
를 선언한다.
어노테이션이 필수는 아니며, 없어도 함수형 인터페이스로 사용할 수 있으나, 어노테이션을 붙이면 함수가 두 개 이상일 시 컴파일 타임에 어노테이션 프로세서가 이를 잡아내 컴파일 에러를 내어 메소드를 하나만 두도록 강제하므로, 어노테이션을 추가하는 것이 권장된다.
java 에서 제공되며 가장 기본적으로 사용되는 함수형 인터페이스에는 Consumer, Predicate, Funcion, Supplier 네 가지가 있다.
input 이 있고, output이 없는 인터페이스를 제공한다.
print 등 인풋이 있으나 내부적으로만 로직이 처리되고 메소드가 종료되는 람다식 정의 혹은 메소드 참조에 사용된다.
public static void main(String[] args) {
List<Integer> nums = new ArrayList<>();
nums.add(1);
nums.add(2);
nums.add(3);
Consumer<Integer> consumer = System.out::println;
nums.forEach(consumer);
}
input이 있고, boolean 타입을 반환한다.
입력받은 값을 통해 특정 상황을 검증하는데에 사용된다.
public static void main(String[] args) {
List<Integer> nums = new ArrayList<>();
nums.add(1);
nums.add(2);
nums.add(3);
Predicate<Integer> isOne = (num) -> num.equals(1);
List<Integer> onlyOne = nums.stream().filter(isOne).collect(Collectors.toList())
}
input과 return이 모두 있다.
public static void main(String[] args) {
List<Integer> nums = new ArrayList<>();
nums.add(1);
nums.add(2);
nums.add(3);
Function<Integer, Test> function = Test::new; // int 를 파라미터로 받는 생성자를 참조
List<Test> tests = nums.stream().map(refer).toList();
}
input이 없고 return값만 있다. 기본 생성자 등을 참조할 때 사용할 수 있다.
Supplier<Test> supplier = Test::new;
이외에도 java에서 제공하는 함수형 인터페이스가 여럿 있으나, 모두 위 네 개의 인터페이스 중 하나에서 파생된 것이므로 위 네 가지를 먼저 알고있는 것이 좋겠다.