티스토리 뷰

Item44는 표준 함수형 인터페이스를 사용하라 말한다

람다 등장 이전에 구현체마다 다른 행동을 지정하기 위해 사용하는 방법으로 템플릿 메서드 패턴이 있었다

상위 클래스의 메서드를 오버라이딩해 동작을 변경할 수 있는데 아래와 같은 형태다

public abstract class Animal {

  void yahoo() {
    System.out.println("YAHOO");
  }
}

public class Cat extends Animal {

  @Override
  void yahoo() {
    System.out.println("CAT YAHOO");
  }
}

public static void main(String[] args) {
  Animal animal = new Cat();
  animal.yahoo();
}

 

실제 동작 시킬 때 상위 타입으로 선언하고 메서드를 호출하더라도

호출 계층 상 인스턴스 -> 클래스 -> 상위 클래스 순으로 메서드가 있는지 확인하기 때문에 구현체의 메서드가 호출된다

이런 방식도 나쁘지 않지만 필요한 행동이 아주 다양할 때 문제가 될 수 있다

필요한 행동의 수만큼 메서드를 재정의한 클래스가 늘어나고 관리가 어려워진다

함수형 인터페이스를 사용해 익명 객체로 처리하는 방법도 있으나 이 보다 우아한 람다를 이용하자

 

위의 예시에서 클래스 마다 달라지는 것은 출력할 내용이므로 문자열을 받아 소비만 하는 형태다

Consumer<String>이 이를 위한 표준 함수형 인터페이스다

public static void main(String[] args) {
  Consumer<String> c = s -> System.out.println(s + " YAHOO");
  c.accept("DOG");
}

 

표준 함수형 인터페이스를 사용하면 인터페이스를 만들 필요도 없고 구현 클래스는 더더욱 만들 필요가 없어진다

함수형 인터페이스를 사용하는 메서드를 만들어두거나 실제 코드가 동작해야 하는 위치에 람다를 사용하면 된다

이를 응용하면 동작 자체를 메서드 인자로 받아 고차 함수로 사용할 수도 있다

java.util.function 에는 이미 수많은 함수형 인터페이스가 존재한다

자바 이용자 대부분이 유용하게 쓸만 한 케이스를 전부 만들어 둔 것이다

 

 

성능을 위한 기본 타입 함수형 인터페이스도 제공한다

이 부분은 비단 함수형 인터페이스 뿐만 아니라 코드를 작성할 때 항상 주의를 기울여야 할 부분이다

오토 박싱과 언박싱에 관한 문제로 JVM이 알아서 해주니 얼렁뚱땅 넘어가면 성능이 박살날 수 있다

 

표준 함수형 인터페이스와 구조적으로 같더라도 새로이 작성해야 하는 경우가 있다
Comparator<T> 가 대표적인데 Comparator와 비교해 유사한 특성이 많다면 직접 작성을 고민해 볼 수 있다

ToIntBiFunction<T, U>와 구조적으로 같은데 왜 따로 작성해야 할까? 그 이유는 다음과 같다
1. 다양한 API 에서 사용되는데 Comparator라는 이름이 직관적으로 무엇을 하는지 잘 알려준다
2. 반드시 따라야 하는 규약이 있다
3. 비교자들을 변환하고 조합해주는 유용한 메서드들이 많다

 

표준 함수형 인터페이스를 사용해야 할 세세한 이유를 살펴봤으나 사실 간단하게 대답이 가능하다

이미 만들어진 걸 뭐하러 새로 작성하겠는가?, 표준이 있는데 뭐하러 호환되지 않을 방식을 사용하겠는가?

댓글
링크
글 보관함
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Total
Today
Yesterday