Java가 람다를 지원하면서, API 작성 모범 사례도 크게 바뀜
정적 팩터리 메서드
: 객체 생성의 역할을 하는 클래스 메서드
- 직접적으로 생성자를 통해 객체를 생성하는 것이 아닌, 메서드를 통해서 객체를 생성하는 것
- 네이밍 컨벤션
from: 하나의 매개 변수를 받아서 객체를 생성of: 여러개의 매개 변수를 받아서 객체를 생성getInstance|instance: 인스턴스를 생성. 이전에 반환했던 것과 같을 수 있음.newInstance|create: 새로운 인스턴스를 생성get[OtherType]: 다른 타입의 인스턴스를 생성. 이전에 반환했던 것과 같을 수 있음.new[OtherType]: 다른 타입의 새로운 인스턴스를 생성.
메서드 참조 - Java의 :: (더블 콜론)
: 메서드 레퍼런스라고도 불림. 자바 8버전에서 소개됨. 람다식과 똑같은 기능을 함
- 람다식과의 차이 : 인스턴스를 활용하여 메서드를 전달힘
- 사용처
- 사용하는 람다식이 기존에 있는 인스턴스의 메서드와 동일하면, 메서드 러퍼런스로 대체 가능
- 정적 메서드, 인스턴스 메서드의 메서드 레퍼런스로 사용 가능
strs.forEach(str -> System.out.println(str));strs.forEach(System.out::println);
LinkedHashMap
removeEldestEntry를 재정의하면 캐시로 사용 가능!
protcted boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > 100;
}
단, 위 메서드는 인스턴스 메서드!
만약 LinkedHashMap이 함수객체를 받는 정적 팩터리나 생성자를 제공하여 구현했다면, 이야기가 달라짐. 생성자에 넘기는 함수 객체가 이 맵의 인스턴스 메서드가 아니기 때문에, 맵은 자기 자신도 함수 객체에 건네줘야 하고.... 이를 반영하면 다음과 같은 함수형 인터페이스로 선언되게 된다.
EldestEntryRemovalFunction 함수형 인터페이스 (사실 불필요)
@FunctionalInterface interface EldestEntryRemovalFunction<K, V> {
boolean remove(Map<K, V> map, Map.Entry<K, V> eldest);
}
사용시 장점
즉, 필요한 용도에 맞는 게 있다면, 직접 구현하지 말고 표준 함수형 인터페이스를 사용하라.
Predicate 인터페이스BiPredicate<Map<K, V>, Map.Entry<K, V>> : 앞의 EldestEntryRemovalFunction 대신 사용 가능! UnaryOperator<T>
- 인수가 1개인 연산 인터페이스
- T apply(T t)
- String::toLowerCase
BinaryOperator<T>
- 인수가 2개인 연산 인터페이스
- T apply(T t1, T t2)
- BigInteger::add
Predicate<T>
- 인수가 하나를 받아 boolean을 반환하는 함수
- boolean apply(T t)
- Collection::isEmpty
Function<T, R>
- 인수와 반환 타입이 다른 함수
- R apply(T t)
- Arrays::asList
Supplier<T>
- 인수를 받지 않고 값을 반환(혹은 제공)하는 함수
- T get()
- Instant::now
Consumer<T>
- 인수를 하나 받고 반환값은 없는(특히 인수를 소비하는) 함수
- void accept(T t)
- System.out::println
기본 인터페이스 : int, long, double 용으로 각 3개씩 변형이 생겨남
IntPredicate : int를 받는 predicateLongBinaryPredicate : long을 받아 long 반환하는 predicate유일하게 매개변수화된 변형 : Function
LongFunction<int[]> : long 인수를 받아 int[]를 반환함인수와 같은 타입을 반환하는 함수 : UnaryOperator
입력과 결과의 타입이 항상 다른 함수 : Function
ToResult : 입력과 결과 타입이 모두 기본 타입이면 사용하는 접두어LongToIntFunction : long으르 받아 int를 반환ToLongFunction<int[]> - int[] 인수를 받아 long을 반환함(총 3개)BiPredicate<T, U>, BiFunction<T, U, R>, BiConsumer<T, U>에는 인수를 2개씩 받는 변형이 있음BiFunctionToIntBiFunction<T, U>ToLongBiFunction<T, U>ToLongBiFunction<T, U>ConsumerObjDoubleConsumer<T>ObjIntConsumer<T>ObjLongConsumer<T>BooleanSupplier : boolean을 반환하도록 한 Supplier의 변형이렇게 총 43개!
- 솔직히 다 외우기에는 수도 많고 규칙성도 부족함.
- 하지만 실무에서 자주 쓰이는 함수형 인터페이스 중 상당수를 제공함
- 필요할 때 찾아 쓸 수 있을 만큼 범용적인 이름 사용함
표준 함수형 인터페이스 대부분은 기본 타입만 지원. 그렇다고 해서 기본 함수형 인터페이스에 박싱된 기본 타입을 넣어 사용하지는 말자!
단, 직접 함수형 인터페이스를 만들어야 함!