함수형 인터페이스( Functuional Interface )
。추상메소드가 오직 1개만 정의된인터페이스
▶인터페이스 구현체를 일급객체로서 생성하기 위해추상메소드를 1개로 제한
。함수형 인터페이스를 통해JAVA에서 함수형 프로그래밍이 가능.
ex )Runnable 인터페이스의 경우에도 오직 1개의추상메서드(run())만 존재하므로,함수형 인터페이스
。인터페이스를 구현한구현클래스의객체없이도인터페이스를익명클래스또는람다식을 통해인터페이스 구현체를 생성
▶ 단인터페이스는구현메소드가 1개인함수형 구현메소드이어야 한다
。JAVA 8부터Interface에static 메소드 , default 메소드를 포함할 수 있는데, 해당메소드를 같이 포함해도함수형 인터페이스로서 기능할 수 있다.
▶static 메서드 , default 메서드는자식클래스에서 반드시 구현해야하는추상메소드가 아니므로
인터페이스 - Default Method
함수형 인터페이스의추상 메서드를 오직 하나만 설정하는 이유?
。JAVA에서 함수형 프로그래밍을 수행하는 경우인터페이스 구현체를일급객체특성을 이용하여추상메서드에함수를 정의하고변수로서 전달하는매개체역할을 수행
▶ 이로 인해추상메서드는 오직 하나로 정의하여 해당추상메서드에메서드 오버라이딩을 통해함수 기능을 작성한인터페이스 구현체를변수로 간주하여프로그래밍을 수행
@FunctionalInterface
。함수형 인터페이스에명시적으로@FunctionalInterface를 명시.
▶추상메서드가 2개 이상되는 실수를컴파일 단계에서 방지 가능.// 명시적으로 표현 @FunctionalInterface interface Calculator{ int calculate(int a, int b); }
인터페이스/추상클래스가 직접구현체를 만들 수 없는 이유?
。추상메서드에실행 로직을 정의할 수 없으므로new를 통해인터페이스또는추상클래스의구현체를 생성할 수 없음.
▶ 이로 인해,익명클래스를 통해추상메서드의실행 로직을 정의하는 경우인터페이스 객체를 직접 생성할 수 있음.@FunctionalInterface public interface Ainterface{ void a(); // 추상메서드 }▶
인터페이스정의 시추상메서드의실행 로직을 작성할 수 없어인터페이스자체로구현체를 생성할 수 없다.Ainterface concrete = new Ainterface( @Override public void a(){ // 실행로직 } );▶ 다음처럼
추상메서드를메서드 오버라이딩시new를 통해서interface 구현체를 직접 생성할 수 있음,Ainterface concrete = () -> { // 실행로직 };▶
람다 표현식으로 축약해서 구현할 수 있음
함수형 인터페이스 구현체를 생성하는 방법
。인터페이스 구현체는추상메서드의로직을 정의해야구현체를 생성할 수 있다.
▶익명클래스 / 람다식을 통해추상메서드를메서드 오버라이딩하면서인터페이스 구현체생성
。기존함수형 인터페이스 구현체생성 시인터페이스 구현 클래스를 별도로 정의 및구현체 객체를 생성해서업캐스팅을 통해 구현하는 단점이 존재.
▶ 한번만객체로 만드는데 사용되는클래스를 정의하는건 비효율적이므로익명클래스,람다식을 통해인터페이스 구현체생성
함수형 인터페이스 구현체를익명클래스를 통해 생성하여 사용
。익명 클래스: 일회용으로 생성되는 이름 없는클래스// 함수형 인터페이스 @FunctionalInterface interface IFunctional{ int add(int a , int b); // 추상메소드 1개 default int noRelation(int a){ // 추상메소드가 아니므로 상관 X return 2; } } public class Main { public static void main(String[] args) { // 익명클래스로 추상메서드의 메서드 오버라이딩을 통해 인터페이스 구현체 생성 IFunctional addFunction = new IFunctional(){ @Override public int add(int a , int b){ return a+b; } }; System.out.println(addFunction.add(1,2)); // 3 도출 } }
함수형 인터페이스 구현체를람다식을 활용하여 생성
。람다식을 통해함수형 인터페이스 구현체생성 시 매번 새롭게 생성되는일회성의코드블록으로인터페이스 구현체가 생성되므로 해당코드블록은 변경될 수 없으므로불변이 보장
▶병렬 프로그래밍에서람다식이 많이 사용되는 이유
。함수형 인터페이스에 한해서만구현체생성 가능.// 함수형 인터페이스 @FunctionalInterface interface IFunctional{ int add(int a , int b); // 추상메소드 1개 default int noRelation(int a){ // 추상메소드가 아니므로 상관 X return 2; } } public class Main { public static void main(String[] args) { // 람다식으로 추상메서드의 메서드 오버라이딩을 통해 인터페이스 구현체 생성 IFunctional addFunction = ( a,b ) ->{ return a+b; } System.out.println(addFunction.add(1,2)); // 3 도출 } }。 이때 내부 로직이 1줄인 경우
return과{}를 생략할 수 있다.IFunctional addFunction = ( a,b ) -> a+b;
자바에서 기본적으로 제공하는함수형 인터페이스
。Runnable등이 존재.
Predicate<T>:
Predicate<Type> predicate = 람다식
。입력 값을 받아서boolean값을 반환하는함수형 인터페이스
。함수형 인터페이스를 요구하는 특정 List객체의Method에Predicate를 사용 시매개변수를 input 받아Predicate의람다식구문을 수행 후Boolean을 반환.
▶ 조건이 참이면 true, 거짓이면 false를 return.
。주로Stream.filter(함수형인터페이스)의 조건을 설정하는 용도로 활용
Predicate<? super 클래스타입>:
。해당 Class type뿐만 아닌 부모 Class Type까지 적용할 수 있는 predicate를 의미.
활용례 )private static List<Todo> todos = new ArrayList<>(); static { todos.add(new Todo(todosCount++,"wjdtn747","Learn AWS", LocalDate.now().plusYears(1),false)); todos.add(new Todo(todosCount++,"wjdtn0619","Learn DevOps", LocalDate.now().plusYears(2),true)); todos.add(new Todo(todosCount++,"wjdtn3902","Learn FullStackDevelopment", LocalDate.now().plusYears(3),false)); } Predicate<? super Todo> predicate = todo -> todo.getId() == 3; todos.removeIf(predicate);▶
List객체.removeIf(함수형인터페이스)에predicate를 전달하여Static List내부의Todoinstance 가 각각Predicate의람다식에 의해 처리 후true를 반환 시 해당Todoinstance를Static List에서 삭제.
list객체.removeif(함수형인터페이스):
。해당List객체의 모든 각 요소에대해predicate를 실시한 후 해당 조건에 대해true이면 삭제