Item 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)를 다시 한번 꼭 읽어 볼것!!!

결론