Skip to content

Latest commit

 

History

History
110 lines (79 loc) · 3.65 KB

30.이왕이면 제네릭 메서드로 만들라.md

File metadata and controls

110 lines (79 loc) · 3.65 KB

제네릭 메서드

클래스와 마찬가지로, 메서드도 제네릭으로 만들 수 있다.

ex. Collections의 알고리즘 메서드 (binarySearch, sort 등)

제네릭 메서드 작성법은 제네릭 타입 작성법과 비슷하다.

로타입 사용 - (아이템 26 - 수용 불가)

public class BadCase {

    public static Set union(Set s1, Set s2) {
        Set result = new HashSet<>();
        result.addAll(s2);
        return result;
    }
}
  • 컴파일은 되지만, 경고가 발생한다. (타입 안전하기 않기 때문에)

제네릭 메서드

public class GoodCase {

    public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
        Set<E> result = new HashSet<>(s1);
        result.addAll(s2);
        return result;
    }
}
  • 타입안전하게 만들 수 있다.
  • 타입 매개변수 목록은 메서드의 제한자와 반환타입 사이에 온다.
    • 타입 매개변수 목록 : <E>
    • 반환 타입 : Set<E>
  • 타입 매개변수의 명명규칙은 제네릭 메서드, 제네릭 타입이 모두 같다.
  • 한정적 와일드카드 타입 (아이템 31)을 사용하여 더 유연하게 개선할 수 있다.

제네릭 싱글턴 팩터리 패턴

제네릭은 런타임에 타입 정보가 소거되므로, 하나의 객체를 어떤 타입으로든 매개변수화 할 수 있다.

이렇게 하기 위해서 요청한 타입 매개 변수에 따라 불변 객체의 타입을 요청한 타임 매개변수에 맞게 변경해주는 정적 팩토리를 만들어야 한다.

public class GenericSingleton {

    private static UnaryOperator<Object> IDENTITY_FN = (t) -> t;

    @SuppressWarnings("unchecked")
    public static <T> UnaryOperator<T> identityFunction() {
        return (UnaryOperator<T>) IDENTITY_FN;
    }
}
  • 해당 예시는 항등 함수를 사용하고 있으며, 어떤 타입이어도 타입 안전하기 떄문에 SuppressWarnings("unchecked")를 사용해서 오류를 제거한다.

재귀적 타입 한정

상대적으로 드물지만, 자기 자신이 들어간 표현식을 사용하여 타입 매개변수의 허용 범위를 한정할 수 있다.

이는 주로 Comparable 인터페이스 (아이템 14)와 함께 쓰인다.

public interface Comparable<T> {

    int compareTo(T o);
}

여기서 타입 매개변수 T는 Comparable을 구현한 타입이 비교할 수 있는 원소의 타입을 정의하며, 거의 모든 타입은 자신과 같은 타입의 원소와만 비교할 수 있다.

public class RecursiveTypeBoundEx {

    public static <E extends Comparable<E>> E max(Collection<E> c);
}

타입 한정인 <E extends Comparable<E>>는 "모든 타입 E는 자신과 비교할 수 있다"라고 읽을 수 있다. 즉, 상호 비교 가능하다는 뜻이다.

public class RecursiveTypeBoundEx {

    public static <E extends Comparable<E>> E max(Collection<E> collection) {
        if (collection.isEmpty()) {
            throw new IllegalArgumentException("비어 있습니다.");
        }

        E result = null;
        for (E e : collection) {
            if (result == null || e.compareTo(result) > 0) {
                result = Objects.requireNonNull(e);
            }
        }
        return result;
    }
}

정리

  • 이번 아이템에서 설명한 내용들은 와일드카드를 사용한 변형 (아이템 31), 셀프 타입 관용구(아이템 2)를 이해하면 더 잘 활용할 수 있을 것이다.
  • 명시적으로 형변환하는 메서드보다 제네렉 메서드가 더 안전하고, 사용하기 쉽다.
  • 형변환을 해줘야하는 기존 메서드는 제네릭하게 만들자. (아이템 26 연관됨)