1 minute read

item 30 이왕이면 제너릭 메서드로 만들라.

  • 클래스와 마찬가지로 메서드도 제너릭으로 만들 수 있다.
  • 메서드 선언시에 필요한 원소 타입들을 타입 매개변수로 명시하고, 메서드 내에서도 타입 매개변수를 사용하도록 수정한다.
public static <E> Set<E> union(Set<E> s1, Set<E> s2) {   
	Set<E> result = new HashSet<>(s1);
    result.addAll(s2);
    return result;
}

public static void main(String[] args) {
	Set<String> guys = Set.of("톰", "딕", "해리");
	Set<String> stooges = Set.of("래리", "모에", "컬리");   
	Set<String> aflCio = union(guys, stooges);   
	System.out.println(aflCio);
}

제네릭 싱글턴 팩터리

  • 불변 객체를 여러 타입으로 활용할 수 있게 한다.
  • 제너릭은 런타임에 타입 정보가 소거되므로, 요청한 타입 매개변수에 맞게 객체의 타입을 바꿔주는 정적 팩터리를 만들어야 한다.
private static UnaryOperator<Object> IDENTITY_FN = (t) -> t;

@SuppressWarnings("unchecked")
// 다음 함수는 항등함수(입력 값을 그대로 반환)이므로 type-safe하다.
// 때문에 위 어노테이션을 사용해도 문제가 되지 않는다
public static <T> UnaryOperator<T> identityFunction() {
	return (UnaryOperator<T>) IDENTITY_FN;
}

public static void main(String[] args) {
// 형변환을 하지 않아도 컴파일 오류나 경고가 발생하지 않는다.
	String[] strings = { "삼베", "대마", "나일론" };
    UnaryOperator<String> sameString = identityFunction();
    
    for (String s : strings)
        System.out.println(sameString.apply(s));
    
    Number[] numbers = { 1, 2.0, 3L };
    UnaryOperator<Number> sameNumber = identityFunction();    
    
    for (Number n : numbers)
        System.out.println(sameNumber.apply(n));
}
  • 자기 자신이 들어간 표현식을 사용해 타입 매개변수의 허용 범위를 한정할 수도 있다. (재귀적 타입 한정)
    • 보통 Comparable 인터페이스와 함께 쓰인다.
public static <E extends Comparable<E>> E max(Collection<E> c){
	if (c.isEmpty())        
		throw new IllegalArgumentException("컬렉션이 비어 있습니다.");    
	E result = null;
    for (E e : c)
	    if (result == null || e.compareTo(result) > 0)
            result = Objects.requireNonNull(e);
    return result;
}

Leave a comment