우테코에서 글렌이 기본형 함수형 인터페이스에 대해 소개해줬다.
그런데 함수형 인터페이스가 뭐지..?
한번 알아보도록 하자.
함수형 인터페이스란?
하나의 추상 메소드를 지정하는 인터페이스다
모던 자바 인 액션 中
쉽게말해 추상메소드가 하나인 인터페이스를 의미한다.
@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이라는 키워드를 얻을 수 있다.
자세한 내용은 이곳에서 다루지는 않겠다.
함수형 인터페이스를 보고 어떻게 동작하는지 말로 설명할 수 있게 되었다.
어떤 로직을 봤을 때 아! 함수형 인터페이스로 표현할 수 있겠구나! 라는 생각이 들 수 있을 정도로 익숙해지는 시간을 가져보는것이 중요할 것 같다.