본문 바로가기
effective java

Item 52. 다중정의는 신중히 사용하라

by mjjang 2022. 3. 6.
public class CollectionClassifier {

    public static String classify(Set<?> s) {
        return "집합";
    }

    public static String classify(List<?> list) {
        return "리스트";
    }

    public static String classify(Collection<?> c) {
        return "그 외";
    }

    public static void main(String[] args) {
        Collection<?>[] collections = {
                new HashSet<>(),
                new ArrayList<>(),
                new HashMap<String, String>().values()
        };

        for (Collection<?> c : collections) {
            System.out.println(classify(c));
        }
    }
}

코드를 실행하면 어떤 결과가 나올까요? 집합, 리스트, 그 외를 차례로 출력할 것 같지만

실제로는 그 외만 세 번 출력됩니다. 그 이유는 다중정의(overloading)된 classify 중 어느 메서드를 호출할지가

컴파일타임에 정해지기 때문입니다.


intellij에서 Set, List를 매개 변수로 받는 classify 메서드는 사용되지 않는다고 나온다.

이처럼 직관과 어긋나는 이유는 재정의한 메서드(Overiding)는 동적(런타임)에 선택되고, 다중정의 한 메서드(overoding)는 정적(컴파일타임)으로 선택되기 때문입니다.

다중정의가 혼동을 일으키는 상황을 피하는 방법

  • 매개변수 수가 같은 다중정의는 만들지 않는다.
    • 서로 다른 함수형 인터페이스도 같은 위치의 인수로 받지 말자.
  • 다중정의하는 대신 메서드 이름을 다르게 짓는다.
    • ObjectOutputStream클래스에 writeInt(int), writeLong(long)
  • 위에 방법들이 불가능하다면 다중정의 메서드들이 모두 동일하게 동작하도록 만들자

public boolean contentEquals(StringBuffer sb) // java 4 
public boolean contentEquals(CharSequence cs) // java 5

상대적으로 특수한(StringBuffer) 다중정의 메서드가 덜 특수한(CharSequence) 다중 정의 메서드로 일을 넘겨버리면
동일한 동작을 보장할 수 있다.

댓글