함수형 인터페이스

주노·2023년 3월 27일
0

기술부채 알쓸신잡

목록 보기
2/22
post-thumbnail

서론

우테코에서 글렌이 기본형 함수형 인터페이스에 대해 소개해줬다.
그런데 함수형 인터페이스가 뭐지..?

한번 알아보도록 하자.

함수형 인터페이스

함수형 인터페이스란?

하나의 추상 메소드를 지정하는 인터페이스다
모던 자바 인 액션 中

쉽게말해 추상메소드가 하나인 인터페이스를 의미한다.

@FunctionalInterface
public interface GameAction {
    void execute(final List<String> commands);
}

Java에서는 @FunctionalInterface 라는 어노테이션을 통해 해당 인터페이스가 함수형 인터페이스임을 명시할 수도 있다.

이는 인터페이스가 함수형 인터페이스 형식을 따르지 않으면 컴파일 단계에서 오류를 발생시킨다.

함수형 인터페이스 왜 쓰는데?

함수형 인터페이스를 이해하기에 앞서 람다식을 이해할 필요가 있다.

람다식?

람다식이란 메서드로 전달할 수 있는 익명함수를 간략하게 표현한 것을 의미한다.

간결한 방식으로 코드를 전달할 수 있다는 장점이 있다.

어떻게 사용하길래 간결한 방식이 되는걸까?

람다식의 사용

// 파라티터 화살표 바디
(o1, o2) -> o2 - o1;

람다 표현식은 파라미터, 화살표, 바로 이루어진다.

그래서 어떻게 쓰는건데?

자바에서는 기본 함수형 인터페이스를 몇가지 제공해준다.
만들어 쓸 수도 있지만 일단은 제공하고있는 기본 함수형 인터페이스에 대해 간략하게 알아가보자.

  • Function<T, R>
  • UnaryOperator<T>
  • Consumer<T>
  • Predicate<T>
  • Supplier<T>

Funciton<T, R>

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
	...
}

T 타입 인자를 받고 R타입 객체를 리턴한다.
라고 읽을 수 있다.

apply() 메소드를 통해 사용할 수 있다.

예를 들어 다음과 같이 사용할 수 있다.

@Test
public void 함수를_반환_값으로_활용하는_예제() {
    Function<String, Integer> toInt = value -> Integer.parseInt(value);
    final Integer number = toInt.apply("100");
    //toInt(100);
    assertThat(number).isEqualTo(100);
}

위 메소드는 String 값을 받아서 Integer.parseInt 메소드를 통해 Integer로 반환해주는 함수형 인터페이스 toInt에 대한 내용이다.

UnaryOperator<T>

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
    static <T> UnaryOperator<T> identity() {
        return t -> t;
    }
}

T 타입 인자를 받고 T타입 객체를 리턴한다.
라고 읽을 수 있다.

identity() 메소드로 사용할 수 있다.

위에서 설명한 Function<T, R>인터페이스와 동일하나 입력값과 반환값이 동일한 타입이다. 정도로 이해하면 될 것 같다.

예를 들어 다음과 같이 사용할 수 있다.

UnaryOperator<String> appendEndLine = value -> value + System.lineSeparator();

System.out.print(appendEndLine.apply("hello"));
System.out.print(appendEndLine.apply("world"));

위 메소드는 String 값을 받아서 개행(System.lineSeparator())를 끝에 추가한 String을 반환하는 함수형 인터페이스 appendEndLine에 대한 내용이다.

Consumer<T>

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);   
	...
}

T 타입 인자를 받아 사용한다.
라고 읽을 수 있다.

accept() 메소드를 통해 사용할 수 있다.

예를 들어 다음과 같이 사용할 수 있다.

final Consumer<String> print = input -> System.out.println(input);

print.accept("HelloWorld!");

위 메소드는 String 값을 받아서 출력하는 함수형 인터페이스 print에 대한 내용이다.

Predicate<T>

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
    ...
}

T 타입의 객체를 인자로 받아 boolean 결과를 반환한다.
라고 읽을 수 있다.

test() 메소드를 통해 사용할 수 있다.

예를 들어 다음과 같이 사용할 수 있다.

final Predicate<Integer> isPositive = number -> number > 0;

isPositive.test(3) // true
isPositive.test(-3) // false

위 메소드는 Integer 값을 받아서 해당 숫자가 양수인지 boolean으로 반환하는 함수형 인터페이스 isPositive에 대한 내용이다.

Supplier<T>

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

T 타입의 값을 반환한다.
라고 읽을 수 있다.

get() 메소드를 통해 값을 반환받는다.

예를 들어 다음과 같이 사용할 수 있다.

Supplier<String> givenString = () -> "StringValue";

단순히 값을 반환하는 함수형 인터페이스다.
왜 사용할까? 의구심이 드는 인터페이스다.

Lazy Evaluation이라는 키워드를 얻을 수 있다.
자세한 내용은 이곳에서 다루지는 않겠다.

결론

함수형 인터페이스를 보고 어떻게 동작하는지 말로 설명할 수 있게 되었다.

어떤 로직을 봤을 때 아! 함수형 인터페이스로 표현할 수 있겠구나! 라는 생각이 들 수 있을 정도로 익숙해지는 시간을 가져보는것이 중요할 것 같다.

Reference

Java 8 함수형 인터페이스 (Functional Interface)

Java : 함수형 인터페이스

profile
안녕하세요 😆

0개의 댓글