아이템 41. 오버로딩할 때는 주의하라.
41. 오버로딩할 때는 주의하라.
public class CollectionClassifier {
public static String classify(Set<?> set){
return "Set";
}
public static String classify(List<?> list){
return "List";
}
public static String classify(Collection<?> collection){
return "Unknown Collection";
}
public static void main(String[] args){
Collection<?>[] collections = {
new HashSet<String>(),
new ArrayList<BigInteger>(),
new HashMap<String, String>().values()
};
collections.forEach(c->System.out.println(classify(c)));
}
}
위 프로그램을 실행 하면, Set, List, Unknown Collection을 순서대로 출력할꺼라 예상하지만, “Unknown Collection”만 세 번 출력 한다.
그 이유는 classify
메서드는 오버로딩되어 있어 직관적으로 봤을때,
각각 다른 인자의 메소드를 호출 할 것으로 기대하지만,
오버로딩된 메서드는 컴파일 시점에 정적으로 검증되지만,
__인자로 전달 되는 클래스 정보는 동적으로 선택__되기 때문에
Set이나 List의 상위 개념인 Collection이 클래스의 우선순위가 높으므로
classify(Collection<?> collection)
메서드가 3번 호출된다.
해결책
public static String classify(Collection<?> c) {
return c instanceof Set ? "Set" :
c instanceof List ? "List" : "Unknown Collection";
}
규칙 41. 오버로딩할 때는 주의하라. (258.p ~ 263.p)를 다시 한번 꼭 읽어 볼것!!!
결론
- 메서드를 오버로딩 할 수 있다고 해서 반드시 그래야 하는 것은 아니다., 인자 개수가 같은 오버로딩 메서드를 추가하는 것은 일반적으로 피해야 한다. 특히 같은 상속 관계를 같는 클래스나, 같은 이름을 같는 제니릭 타입을 오버로딩할때는 많은 주의가 필요하다.