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개씩 받는 변형이 있음BiFunction
ToIntBiFunction<T, U>
ToLongBiFunction<T, U>
ToLongBiFunction<T, U>
Consumer
ObjDoubleConsumer<T>
ObjIntConsumer<T>
ObjLongConsumer<T>
BooleanSupplier
: boolean을 반환하도록 한 Supplier의 변형이렇게 총 43개!
- 솔직히 다 외우기에는 수도 많고 규칙성도 부족함.
- 하지만 실무에서 자주 쓰이는 함수형 인터페이스 중 상당수를 제공함
- 필요할 때 찾아 쓸 수 있을 만큼 범용적인 이름 사용함
표준 함수형 인터페이스 대부분은 기본 타입만 지원. 그렇다고 해서 기본 함수형 인터페이스에 박싱된 기본 타입을 넣어 사용하지는 말자!
단, 직접 함수형 인터페이스를 만들어야 함!