Post

Item 12 - toString을 항상 재정의하라

toString을 항상 재정의하라

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**  
* 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(' ');
    }
}
  • Object의 toString클래스 이름@16진수로_표현한_해시코드를 반환한다.
  • toString 메서드는 객체를 printlnprintf, 문자열 연결 연산자(+), assert 구문에 넘길 때, 혹은 디버거가 객체를 출력할 때 자동으로 호출된다.
  • 즉, 직접 호출하지 않아도 다른 어딘가에서 쓰일 수 있다.
  • 따라서 toString이 유익한 정보를 반환할 수 있도록 하위 클래스에서 재정의하자.

toString그 객체가 가진 주요 정보 모두를 반환하는게 좋다.

간결하면서 사람이 읽기 쉬운 형태의 유익한 정보를 반환하자.

포맷 문서화 여부를 결정하자

toString 구현 시, 반환 값의 포맷을 문서화할 지 여부를 결정해야 한다.

전화번호나 행렬 같은 값 클래스라면 포맷을 문서에 명시하는 것이 좋다.

포맷을 명시하기로 했다면, 명시한 포맷에 맞는 문자열과 객체를 생성할 수 있는 정적 팩터리생성자를 제공하는 것이 좋다.

포맷을 명시한 예

1
2
3
4
5
6
7
8
9
10
/**
 * 전화번호의 문자열 표현을 반환한다.
 * 이 문자열은 "XXX-YYY-ZZZZ" 형태의 11글자로 구성된다.
 * XXX는 지역 코드, YYY는 프리픽스, ZZZZ는 가입자 번호다.
 */
@Override
public String toString() {
    return String.format("%03d-%03d-%04d",
            areaCode, prefix, lineNum);
}

포맷을 명시하지 않은 예

1
2
3
4
5
6
7
8
@Override
public String toString() {
    return "PhoneNumber{" +
                "areaCode='" + areaCode + '\'' +
                ", prefix='" + prefix + '\'' +
                ", lineNum='" + lineNum + '\'' +
                '}'; 
}

반환 값의 정보를 API로 제공하자

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

ex) PhoneNumber 클래스는 필요한 지역 코드, 프리픽스, 가입자 번호용 접근자를 제공해야 한다.

그렇지 않으면 프로그래머가 반환 값을 직접 파싱해야 한다.

💡 핵심 정리

  • 모든 구체 클래스에서 Object의 toString을 재정의해서 사용하자.
  • 상위 클래스에서 알맞게 재정의한 경우는 예외다.
  • 알맞게 재정의한 toString은 사용하기에도 유용하고 디버깅도 편해진다.
  • 해당 객체에 관한 명확하고 유용한 정보를 읽기 좋은 형태로 반환해야 한다.
This post is licensed under CC BY 4.0 by the author.