아이템 27. 가능하면 제네릭 메서드로 만들것
27. 가능하면 제네릭 메서드로 만들것
static 유틸리티 메서드는 제네릭화하기 좋은 후보다. Collections에 구현된 모든 “알고리즘” 메서드(binarySearch나 sort같은)는 제네릭으로 구현되어 있다.
1. 일반 적인 사용
public static <E> Set<E> union(Set<E> s1, Set<E> s2){
Set<E> result = new HashSet<E>(s1);
result.addAll(s2);
return result;
}
public static void main(String[] args){
Set<String> guys = new HashSet<String>(Arrays.asList("Tom", "Dick", "Harry"));
Set<String> stooges = new HashSet<String>(Arrays.asList("Larry", "Moe", "Curly"));
Set<String> aflCio = union(guys, stooges);
System.out.println( aflCio );
}
2. 제네릭 정적 팩터리 메서드
Map<String, List<String>> m = new HashMap<String, List<String>>();
// 위와 같은 번거러움을 피하기 위해서 아래와 같은 제네릭 정적 메서드 정리하여 사용(guava lib 사용)
public class Maps{
public static <K,V> Hashmap<K,V> newHashMap(){
return new HashMap<K,V>();
}
}
//use
public static void main(String[] args){
Map<String, List<String>> m = Maps.newHashMap();
...
}
3. 제네릭 싱글턴 팩터리 패턴
public interface UnaryFunction<T>{
T apply(T arg);
}
// 위와 같은 항등 함수(identity function)를 구현했다고 가정함
// 항등 함수는 무상태 함수이므로 필요할 때 새 함수를 만드는 것은 낭비이므로 싱글턴으로 객체 생성하여,
// 재사용하도록 아래와 같이 구현
public static final UnaryFunction<Object> IDENTITY_FUNCTION = new UnaryFunction<Object>() {
public Object apply(Object arg){ return arg; }
};
// IDENTITY_FUNCTION은 무상태 객체고 형인자는비한정 인자이므로(unbounded)
// 모든 자료형이 같은 객체를 공유해도 안전함.
@SuppressWarnings("unchecked")@
public static <T> UnaryFunction<T> identityFunction(){
return (UnaryFunction<T>) IDENTITY_FUNCTION;
}
//use
public static void main(String[] args){
String[] strings = {"jute", "hemp", "nylon"};
UnaryFunction<String> sameString = identityFunction();
for(String s : strings)
System.out.println(sameString.apply(s));
}
4. 재귀적 자료형 한정(recursive type bound)
public static <T extends Comparable<T>> T max(List<T> list){
Iterator<T> i = list.iterator();
T result = i.next();
while( i.hasNext() ){
T t = i.next();
if(0 < t.compareTo(result)){
result = t;
}
}
return result;
}
결론
- 제네릭 자료형과 마찬가지로 제네릭 메서드는 클라이언트가 직접 이력 값과 반환값의 자료형을 형변환해야 하는 메서드보다 사용하기 쉽고 형 안정성도 높다.
- 시간 날때 기존 메서드를 제네릭 메서드로 확장해 놓으면, 기존 클라이언트 코드를 깨지 않고도 새 사용자에게 더 좋은 API를 제공할수 있다.