제네릭 타입과 마찬가지로, 클라이언트에서 입력 매개변수와 반환값을 명시적으로 형변환해야하는 메서드보다, 제네릭 메서드가 더 안전하며 사용하기도 쉽다. 형변환 없이 사용하기 위해서는 대부분 제네릭 메서드를 사용한다.
publicstaticSetunion(Set s1,Set s2) {Set result =newHashSet(s1); // raw typeresult.addAll(s2);return result;}
위 코드는 컴파일은 되지만 아래 두가지 경고가 발생한다.
Unchecked call to 'HashSet(Collection<? extends E>)' as a member of raw type 'java.util.HashSet'
Unchecked call to 'addAll(Collection<? extends E>)' as a member of raw type 'java.util.Set'
경고를 없애기 위해서는 타입안정성을 지켜주면 된다.
publicstatic<E>Set<E>union(Set<E> s1,Set<E> s2) {Set<E> result =newHashSet<>(s1); // raw typeresult.addAll(s2);return result;}
다음과 같이 제네릭 메서드로 바꿔주면 경고 문구가 뜨지 않으며, 타입 안전성도 지켜지는 것을 확인할 수 있다.
제네릭 싱글턴 팩터리
때때로 불변 객체를 여러 타입으로 활용할 수 있게 만들어야 하는 경우가 있다. 요청한 타입 매개변수에 맞게 매번 그 객체의 타입을 바꿔주는 정적 팩터리(제네릭 싱글턴 팩터리)를 이용해 구현할 수 있다.
제네릭 싱글턴 팩터리 패턴으로 IDNTITY_FN를 UnaryOperator<T>로 형변환해주는 함수이다. 이때, UnaryOperator<Object>는 UnaryOperator<T>가 아니기 때문에 비검사 형변환 경고가 발생하지만, 항등함수는 입력 값을 수정없이 그대로 반환하는 특별한 함수이므로, T에 어떤 타입이 오든 타입이 안전하기 때문에 @SupperessWarnings로 해당 경고를 없애주었다.
재귀적 타입 한정
이 외에도 자기 자신이 들어간 표현식을 사용하여, 타입 매개변수의 허용 범위를 한정하는 재귀적 타입 한정(recursive type bound) 개념이 있다. 재귀적 타입 한정은 주로 타입의 자연적 순서를 정하는 Comparable 과 함께 사용한다.
매개변수 T는 Comparable<T>를 구현한 타입이 비교할 수 있는 원소의 타입을 정의하며, 실제로 거의 모든 타입은 자신과 같은 타입의 원소와만 비교할 수 있다. Comparable을 구현한 원소의 컬렉션을 입력받는 메서드들은 주로 그 원소들을 정렬, 검색, 비교하는 용도로 사용되며, 해당 용도로 사용하려면 컬렉션에 담긴 모든 원소가 상호 비교될 수 있어야한다.
publicstatic<E extends Comparable<E>>Emax(Collection<E> c) {if (c.isEmpty()) {thrownewIllegalArgumentException("collection is empty"); }E result =null;for (E e : c) {if (result ==null||e.compareTo(result) >0) { result =Objects.requireNonNull(e); } }return result;}
타입한정인 <E extends Comparable<E>>는 "모든 타입 E는 자신과 비교할 수 있다"라는 의미로 해석할 수 있으며, 상호 비교가 가능하다는 것을 의미한다.