[item 12] toString을 항상 재정의하라

김동훈·2023년 5월 28일
1

Effective-java

목록 보기
4/14
post-thumbnail

item12를 들어가면 곧 바로 간결하면서 사람이 읽기 쉬운 형태의 유익한 정보를 반환해야 한다. 는 문장을 볼 수 있다. 이는 이후에 보여줄 Enum의 toString()메소드의 문서 주석에 나오는 programmer-freindly 키워드와 동일한 의미를 가진다고 생각한다.
결국 이번 item12을 정리하게 되면 toString()메소드의 재정의 기준이 이 programmer-freindly에 맞춰서 재정의한다. 인 것 같다. 따라서 이번 게시글은 item12을 공부하며 알게된 여러 클래스의 toString()에 대해 조금 적어보겠다.


우선 책을 보면 대다수의 컬렉션 구현체는 추상 컬렉션 클래스들의 toString()메소드를 상속해 쓴다 고 되어있다. 그럼 흔히 사용하는 HashMap과, HashSet을 확인 해 보자. Enum의 toString() 메소드도 확인해 볼 것이다.

HashMap

HashMap은 AbstractMap을 상속받고있다. 그리고 실제로도 HashMap클래스에는 toString()이 재정의 되어있지 않고, AbstractMap의 toString()을 그대로 사용하고 있음을 확인 할 수 있다.
그리고 여러 Map의 구현체, WeakHashMap, TreeMap, LinkedHashMap, EnumMap 들도 AbstractMap의 toString()을 사용하고 있다.
AbstractMap의 toString()은 다음과 같다.

public String toString() {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        if (! i.hasNext())
            return "{}";

        StringBuilder sb = new StringBuilder();
        sb.append('{');
        for (;;) {
            Entry<K,V> e = i.next();
            K key = e.getKey();
            V value = e.getValue();
            sb.append(key   == this ? "(this Map)" : key);
            sb.append('=');
            sb.append(value == this ? "(this Map)" : value);
            if (! i.hasNext())
                return sb.append('}').toString();
            sb.append(',').append(' ');
        }
    }

toString()을 출력해보면 우리에게 익숙한 형태임을 알 수 있다.

HashSet

HashSet은 AbstractSet을 상속받고 있다. 그리고 AbstractSet은 AbstractCollection을 상속받고 있다. 그래서 이 AbstractCollection의 toString()메소드를 사용하게 된다.
AbstractCollection의 toString()메소드는 다음과 같다.

public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }

HashSet, LinkedHashSet, TreeSet등을 확인 해보자.
toString()을 출력해보면 Set도 익숙한 형태로 보여진다.

Enum

java.lang패키지에 있는 Enum클래스의 toString()은 다음과 같다.

    /**
     * Returns the name of this enum constant, as contained in the
     * declaration.  This method may be overridden, though it typically
     * isn't necessary or desirable.  An enum type should override this
     * method when a more "programmer-friendly" string form exists.
     *
     * @return the name of this enum constant
     */
    public String toString() {
        return name;
    }

단순히 name을 반환하고 있다. 문서 주석을 보면 잘 재정의 하지는 않지만, programmer-friendly한 string이 있는 경우 재정의된다.고 되어있다. 이번 item12와 연결지어 간결하면서 사람이 읽기 쉬운 형태의 유익한 정보의 형태가 바로 programmer-freindly 정도로 이해할 수 있을 것이다.

여기서 한번 생각해 볼만한 점은 toString()메소드가 단순히 name를 반환하고 있고, Enum클래스에는 name()이라는 메소드도 존재하는데 이 또한 단순히 name을 반환 해주고 있다.

/**
     * Returns the name of this enum constant, exactly as declared in its
     * enum declaration.
     *
     * <b>Most programmers should use the {@link #toString} method in
     * preference to this one, as the toString method may return
     * a more user-friendly name.</b>  This method is designed primarily for
     * use in specialized situations where correctness depends on getting the
     * exact name, which will not vary from release to release.
     *
     * @return the name of this enum constant
     */
    public final String name() {
        return name;
    }

문서주석을 보면 toString()메소드는 좀 더 user-freindly한 name을 반환해줄 것 이고, name()메소드는 정확한 name비교 등에 사용될 것 이다. 라는 것을 볼 수 있다. 다시 말하면 name()메소드는 final키워드가 붙어 더이상 재정의를 할 수 없고, toString()은 재정의가 가능하다. 따라서, 필요에 맞게 toString()을 재정의하여 name을 출력하게끔 사용하게 될 것이다.


effective-java스터디에서 공유하고 있는 전체 item에 대한 정리글

profile
董訓은 영어로 mentor

0개의 댓글