Object의 기본 toString 메서드는 단순히 클래스_이름@16진수로_표현한_해시코드 를 반환한다. 이는 우리가 원하는 적합한 문자열을 반환하는 형태가 아니다.

Untitled

toString의 일반 규약에 따라 모든 하위 클래스에서 toString을 재정의 하여 **** 간결하면서 사람이 읽기 쉬운 형태의 유익한 정보를 반환해야 한다.

toString을 재정의하여 얻는 장점

toString을 직접 호출하지 않더라도 객체를 println, printf, 문자열 연결 연산자 (+), assert 구문에 넘길 때 등 다양한 상황에서 사용될 수 있다.

toString을 잘 구현한 클래스는 사용하기에 훨씬 즐겁고, 그 클래스를 사용한 시스템은 디버깅하기 쉽다.

ex. Collection

public abstract class AbstractCollection<E> implements Collection<E> {
    /**
     * Returns a string representation of this collection.  The string
     * representation consists of a list of the collection's elements in the
     * order they are returned by its iterator, enclosed in square brackets
     * ({@code "[]"}).  Adjacent elements are separated by the characters
     * {@code ", "} (comma and space).  Elements are converted to strings as
     * by {@link String#valueOf(Object)}.
     *
     * @return a string representation of this collection
     */
    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(' ');
        }
    }
}

toString 규약

  1. 그 객체가 가진 주요 정보 모두를 반환하는 것이 좋다.
  2. 만약, 객체가 거대하거나 객체의 상태가 문자열로 표현하기에 적합하지 않다면 스스로를 완벽하게 설명할 수 있는 요약 정보(문자열)를 담아야 한다.

toString 구현

반환값의 포맷을 문서화할지 정해야 한다. 포맷을 명시하면 그 객체는 표준적이고, 명확하고, 사람이 읽을 수 있게 된다.

포맷을 명시하기로 했다면, 명시한 포맷에 맞는 문자열과 객체를 상호 전환할 수 있는 정적 팩터리나 생성자를 함께 제공해주면 좋다. 자바 플랫폼의 많은 값 클래스가 따르는 방식이기도 하며, BigInteger, BigDecimal과 대부분의 기본 타입 클래스가 여기에 해당한다.

Untitled

하지만 단점 또한 존재한다. 포맷을 한번 명시하면 (그 클래스가 많이 쓰인다면) 평생 그 포맷에 얽매이게 된다. 만약 향후 릴리스에서 포맷을 변경하게 되면 이를 사용하던 코드들과 데이터들은 엉망이 될 것이다.

포맷을 명시하든 아니든 의도는 분명하게 밝혀야 한다.

포맷 명시 여부와 상관없이 toString이 반환한 값에 포함된 정보를 얻어올 수 있는 API를 제공하자