# ITEM12 toString 을 항상 재정의하라

# toString 일반 규약

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

# Object 의 toString 메서드가 기본적으로 반환하는 문자열

  • 클래스_이름@16진수로_표시한_해시코드
  • PhoneNumber@addbd
  • 간결하지만 전화번호를 직접알려주는 형태가 훨씬 더 유익하다.

# 잘 구현된 toString 메서드 클래스의 장점

  • 사용이 편하다
  • 시스템 디버깅이 쉬워진다.

# toString 이 자동 호출 문맥

  • 객체를 println, printf, 문자열 연결 연산자(+), assert 구문에 넘길 때
  • 디버거가 객체를 출력할 때
  • 작성한 객체를 참조하는 컴포넌트가 오류 메시지를 로깅할 때 자동으로 호출됨

# toString 에 적합한 내용

  • 그 객체가 가진 주요 정보를 모두 반환하는 것이 좋다.
  • 거대한 객체 or 객체 상태가 문자열 표현으로 부적합
    • 요약 정보를 담는다.
    • 맨해튼 거주자 전화번호부(총 1233434324개)
    • Thread[main, 5, main]

# toString 반환값 포맷 문서화

# 장점과 특징

그 객체는 표준적, 명확함, 사람이 읽을 수 있는 특징을 가진다.

  • 전화번호나 행렬 같은 값 클래스 → 문서화 권장
  • 값 그대로 입출력에 사용한다
  • CSV 파일처럼 사람이 읽을 수 있는 데이터 객체로 저장한다
  • 포맷에 맞는 문자열과 객체를 상호전환할 수 있는 정적 팩터리나 생성자를 함께 제공해 주면 좋다. ??

# 단점

포맷을 한번 명시하면(그 클래스가 많이 쓰인다면) 평생 포맷에 얽매인다

  • 이를 사용하는 프로그래머들이 그 포맷에 맞춰 다음과 같은 행위를 할 것이기 때문.
    • 파싱
    • 새로운 객체 생성
    • 영속 데이터로 저장

포맷을 명시하지 않는다면 향후 릴리스에서 정보를 더 넣거나 포맷을 개선할 수 있는 유연성을 얻게 된다.

포맷을 명시하든 아니든 의도는 명확히 밝혀야 한다. 설명을 읽고서도 위와 같은 행위를 하여 피해를 입는다면 사용한 프로그래머의 잘못이다.

/**
* ...
* 상세 형식은 정해지지 않았으며 향후 변경 될 수 있다.
*/
@Override public String toString() { ... }
1
2
3
4
5

단, 포맷을 명시하려면 아주 정확하게 해야 한다.

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

  • 클래스 필드에 대한 정보가 필요한 프로그래머는 toString 의 값을 파싱해야 한다. → 성능저하, 불필요한 작업
    → 향후 포맷을 바꾸면 시스템이 망가진다.

접근자를 제공하지 않으면, 변경될 수 있다고 문서화를 해도
그 포맷이 사실상 준-표준 API 나 다름없다.

# toString 을 재정의 하지 않아도 되는 타입

  • 정적 유틸리티 클래스[4]
  • 대부분의 열거타입[34]은 자바가 이미 완벽한 toString 을 제공

# toString 을 재정의 해야하는 타입

하위 클래스들이 공유해야 할 문자열 표현이 있는 추상클래스 ??

  • 대다수의 컬렉션 구현체는 추상 컬렉션 클래스들의 toString 메서드를 상속해서 쓴다.

# toString 자동생성

  • AutoValue 프레임워크로는 클래스의 의미까지 파악하기 어렵다.
  • 자동생성에 적합하지 않는 타입
    • PhoneNumber 은 표준체계가 있다.
  • 자동생성에 적합하지 않더라도 객체의 값에 관해 아무것도 알려주지 않는 Object 의 toString 보다는 자동생성하는 것이 낫다.