자바의 함수형 인터페이스

포모·2020년 12월 14일
0

JAVA의 기본

목록 보기
8/9

함수형 인터페이스란?

객체지향 언어인 자바가 8로 접어들면서 "함수형 개발 패러다임"을 지원하기 시작했다고 합니다.
이를 통해 자바가 재사용이 가능한 코드 조각을 조금더 만들 수 있게 되고 유연한 개발을 할 수 있는 가능성이 늘어났다고 합니다.

그렇다면 이 함수형 개발 방식은 객체 지향 개발 방식과 무엇이 다를까요?

둘의 가장 큰 차이는 값을 취급하는 단위가 어디까지 인지에 따라 나눌 수 있다고 합니다.


자바는 값(상태)와 행위를 다루기 위한 기본 단위를 객체로 정의하고 이 객체를 클래스라는 형태로 구현하였습니다.


이에 반해 함수형 개발 방식은 행위에 해당하는 부분도 값으로 취급이 가능해졌습니다.
이는 코드 재활용 단위가 클래스에서 함수 단위로 재사용이 가능해지면서 좀 더 유연한 개발을 할 수 있게 됩니다.


함수 단위로 재사용? 🤔

예를 들어 Calculator라는 클래스가 있고 이 Calculator라는 틀의 add 메소드를 실행했다면,

함수형 인터페이스를 통해 add 메소드에 대한 틀을 만들어 바로 재사용할 수 있습니다!

class Calculator {
    public int add(int a, int b) {
        return a+b;
    }
}

public class 함수형_인터페이스 {
    public static void main(String[] args) {
        BinaryOperator<Integer> add = Integer::sum;

        System.out.printf("객체 지향 개발 방식 %d\n", new Calculator().add(3, 5));
        System.out.printf("함수형 개발 방식 %d", add.apply(3, 5));
    }
}

// 출력
// 객체 지향 개발 방식 8
// 함수형 개발 방식 8

함수형 인터페이스 종류

인자와 반환값에 따라 다양한 함수형 인터페이스를 생성할 수 있습니다.

종류인자반환설명
Runnable기본적인 형태의 인터페이스, 인자와 반환값 모두 없음
Supplier<T><T>인자가 없이 제너릭 타입의 반환값만 있는 인터페이스, 항상 같은 값을 반환
Consumer<T><T>제너릭 타입의 인자만 있고 반환값이 없는 인터페이스
Predicate<T><T>Boolean제너릭 타입의 인자와 Boolean 타입의 반환값을 가지는 인터페이스
Function<T, R><T><R>제너릭 타입의 인자와 다른 제너릭 타입의 반환값이 같이 있는 인터페이스
UnaryOperator<T><T, T><T>같은 제너릭 타입의 인자와 반환값을 가지고 있는 인터페이스
BinaryOperator<T><T, T><T>같은 제너릭 타입의 인자 2개를 받고 같은 제너릭 타입의 반환값을 가지는 인터페이스
BiConsumer<T, U><T, U>다른 제너릭 타입의 인자 2개를 받고 반환값이 없는 인터페이스
BiPredicate<T, U><T, U>Boolean다른 제너릭 타입의 인자 2개를 받고 Boolean 타입의 반환값을 가지는 인터페이스
BiFunction<T, U, R><T, U><R>다른 제너릭 타입의 인자 2개를 받고 다른 제너릭 타입의 반환값을 가지는 인터페이스
Comparator<T><T, T>int같은 제너릭 타입의 인자 2개를 받고 Integer 반환값을 가지는 인터페이스, 객체 간의 값을 비교하기 위한 compare 기능을 위한 인터페이스

Consumer

"Consumer"는 매개변수를 소비한다는 의미로, accpet()를 통해 접근하고 리턴값은 가지지 않습니다.

인터페이스명추상메소드설명
Consumer<T>void accept(T t)객체 T를 받아 소비
BiConsumer<T, U>void accept(T t, U u)객체 T, U를 받아 소비
DoubleConsumervoid accept(double value)double 값을 받아 소비
intConsumervoid accept(int value)int 값을 받아 소비
LongConsumervoid accept(long value)long 값을 받아 소비
ObjDoubleConsumer<T>void accept(T t, double value)객체 T와 double 값을 받아 소비
ObjIntConsumer<T>void accept(T t, int value)객체 T와 int 값을 받아 소비
ObjLongConsumer<T>void accept(T t, long value)객체 T와 long 값을 받아 소비

매개변수의 타입에 따라 조금씩 이름이 다르지만, 함수의 수행 로직은 같습니다.


예제

public class 함수형_인터페이스 {
    public static void main(String[] args) {
        Consumer consumer = s -> System.out.println("입력 값 출력 : " + s);
        consumer.accept("hello");
    }
}

// 출력
// 입력 값 출력 : hello

Supplier

Supplier는 매개변수가 없고 리턴 값만 존재하는 get() 메소드를 가집니다.

인터페이스명추상 메소드설명
Supplier<T>T get()T 객체를 리턴
BooleanSupplierboolean getAsBoolean()boolean 값을 리턴
DoubleSupplierdouble getAsDouble()double 값을 리턴
IntSupplierint getAsInt()int 값을 리턴
LongSupplierlong getAsLong()long 값을 리턴

예제

public class 함수형_인터페이스 {
    public static void main(String[] args) {
        Supplier<String> success = () -> {
            return "성공했습니다.";
        };

        String message = success.get();
        System.out.println(message);
    }
}

// 출력
// 성공했습니다.

Function

Function 인터페이스는 매개 변수와 리턴값이 있는 apply()메소드를 가집니다.
이 메소드는 매개값을 리턴값으로 매핑(타입 변화)하는 역할을 합니다.

인터페이스명추상 메소드설명
Function<T, R>R apply(T t)객체 T를 객체 R로 매핑
BiFuction<T, U, R>R apply(T t, U u)객체 T, U을 객체 R로 매핑
DoubleFuction<R>R apply(double value)double을 객체 R로 매핑
IntFuction<R>R apply(int value)int를 객체 R로 매핑
IntToDoubleFuctiondouble apply(int value)int를 double로 매핑
LongToDoubleFunctiondouble applyAsDouble(long value)long을 double로 매핑
ToDoubleBiFunction<T, U>double applyAsDouble(T t, U u)객체 T, U를 double로 매핑

예제

public class 함수형_인터페이스 {
    public static void main(String[] args) {
        Function<String, String> messageFunction = s -> {
            return "메세지 \""+s+"\"를 전송하였습니다.";
        };

        String message = "안녕하세요";
        System.out.println(messageFunction.apply(message));
    }
}
// 출력
// 메세지 "안녕하세요"를 전송하였습니다.

🛴 마무리

함수형 인터페이스를 처음에 올리고, 다시 차근차근 공부해보았는데요.
예제까지 직접 코딩해보면서 정리해보니 이해가 잘 되네요.
뭔가 고생 끝에 정답을 찾은 느낌이 너무 좋습니다ㅠㅠ

다른 좋은 예제나 코드가 있으면 더 업데이트하도록 하겠습니다!!


참고

0개의 댓글