Skip to content

Latest commit

 

History

History
138 lines (92 loc) · 4.12 KB

File metadata and controls

138 lines (92 loc) · 4.12 KB

toString을 항상 재정의하라

1 개요

  • Object의 기본 toString 메서드가 우리가 작성한 클래스에 적합한 문자열을 반환하는 경우는 거의 없다
    • Object의 기본 toString메서드는 클래스_이름@16진수로_표시한_해시코드를 반환한다
  • toString 메서드는 개발자가 직접 호출하지 않더라도, 객체를 println, printf, 문자열 연결 연산자(+), assert 구문에 넘길 때, 혹은 디버거가 객체를 출력하도록 할 때 자동으로 불린다

2 Object의 toString

2.1 Object의 toString 규약

  • 간결하면서 사람이 읽기 쉬운 형태의 유익한 정보를 반환해야한다
  • 모든 하위 클래스에서 이 메서드를 재정의하라

Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method. The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:

getClass().getName() + '@' + Integer.toHexString(hashCode())

Returns: a string representation of the object.

3 toString 재정의

  • 재정의할 때 가장 중요한 건 객체 스스로를 완벽히 설명하는 문자열이어야 한다는 것이다.
  • 보통은 객체가 가진 주요 정보를 모두 반환하는 것이 좋다.

PhoneNumber.java

  • 전화번호처럼 포맷이 정해져 있는 경우, 아래 코드와 같이 재정의하고 주석을 달아서 문서화를 해줄 수도 있다
/** 
 * 전화번호의 문자열 표현을 반환합니다.
 * 이 문자열은 XXX-YYYY-ZZZZ 형태의 11글자로 구성됩니다.
 * XXX는 지역코드, YYYY는 접두사, ZZZZ는 가입자 번호입니다.
 * 
 * 전화번호의 각 부분의 값이 너무 작아 자릿수를 채울 수 없다면
 * 앞에서부터 0으로 채워나간다. 예컨대 가입자 번호가 123이라면
 * 전화번호의 마지막 네 문자는 "0123"이 된다
*/
@Override
public String toString() {
    return String.format("%03d-%04d-%04d", areaCode, prefix, lineNum);
}

4 toString 재정의가 필요하지 않은 경우

  • 유틸리티 클래스는 toString()을 사용할 이유가 없다
  • Enum 은 아래 코드처럼 toString() 이미 정의되어 있으므로 toString()을 재정의하지 않아도 된다.

Enum.java

public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {
  private final String name;
  public String toString() {
    return name;
  }
}

5 예시

5.1 AbstractMap 클래스

public abstract class AbstractMap<K,V> implements Map<K,V> {
  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(' ');
    }
  }
}

5.2 AbstractCollection 클래스

public abstract class AbstractCollection<E> implements Collection<E> {
  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(' ');
    }
  }
}

참고