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

심규환·2022년 3월 20일
0

Effective Java

목록 보기
28/29

매개변수화 타입을 받는 정적 유틸리티 메서드는 보통 제네릭이다. 예를들어 Collections의 '알고리즘' 메서드(binarySearch, sort 등)는 모두 제네릭이다.

다음은 문제가 있는 코드이다. 한번 살펴보자.

public static Set union(Set s1, Set s2){
	Set result = new HashSet(s1);
    result.addAll(s2);
    return result;
}

이 코드를 컴파일하면 정상적으로 컴파일 되지만 두 곳에서 경고가 발생한다.
new HashSet(s1), result.addAll(s2)
경고를 살펴보면 raw type의 맴버를 넣었기 때문에 타입 안전하지 않다는 (unchecked) 경고가 발생한다.

그렇다면 경고를 없애기 위해 타입 안전하게 만들어야 한다. 이를 위해 제네릭을 사용해보자.
타입 매개변수의 위치는 제한자와 반환 타입 사이에 넣어주자.

public static <E> Set<E> union(Set<E> s1, Set<E> s2){
	Set<E> result = new HashSet<>(s1);
    result.addAll(s2);
    return result;
}

이제 경고는 사라지게 된다. 이렇게 작성하면 타입 안전하고 쓰기도 쉽게 된다. 이를 다음장에서 사용할 와일드 카드와 같이 사용하면 좀 더 유연하게 사용이 가능한다. 와일드 카드는 31장에서 살펴볼 것이다.

때로는 싱글턴 팩터리를 사용하여 각 타입에 맞춰서 객체를 사용할 수가 있을 것이다. 이때 제네릭을 사용하면 좀 더 유연하게 사용이 가능하다.
단 하나의 메서드를 만들어 놓는 것으로 다양한 타입으로 사용이 가능하게 해주기 때문이다.
이와 같은 방식이 가능한 이유는 런타임에 타입 정보가 소거 되기 때문이다.

제네릭 싱글턴 팩터리 패턴

// 항등 함수
private static UnaryOperator<Object> IDENTITY_FN = (t) -> t;

@SuppressWarnings("unchecked")
public static <T> UnaryOperator<T> identityFunction(){
	return (UnaryOperator<T>) IDENTITY_FN;
}

IDENTITY_FN을 UnaryOperator 로 형변환하면 비검사 형변환 경고가 발생한다. T가 어떤 타입이든 UnaryOperator는 UnaryOperator가 아니기 때문이다.
하지만 위의 코드는 항등 함수이기 때문에 입력 값을 그대로 반환하게 된다. 그렇기 때문에 타입 안전하고 @SuppressWarnings 로 경고를 제거한다.

아래의 코드는 사용 예시이다.

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(sameString.apply(n));
}

단 하나의 메서드를 제네릭으로 선언하여 다양한 타입으로 사용 가능한 것을 확인할 수 있다.

또 서로 간의 비교가 가능한 Comparable을 구현한 클래스 타입만을 제한하도록 제네릭 선언할 수 있다.
다음 코드를 살펴보자.

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

이는 Comparable을 구현한 E를 담은 컬렉션만을 허용하는 메서드이다. 컬렉션 안의 내용을 비교하기 위해서 사용되는데.
max 라는 메서드 이름답게 컬렉션 안에서 가장 큰 값을 구하게 된다.

위의 많은 예시들 처럼 제네릭을 사용하면 형변환을 안할 수 있도록 도와준다. 이는 코드를 안전하게 해준다. 그러니 가능하면 제네릭을 사용하자.

profile
장생농씬가?

0개의 댓글