# 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
2
3
4
5
단, 포맷을 명시하려면 아주 정확하게 해야 한다.
포맷 명시 여부과 상관 없이 toString 이 반환한 값에 포함된 정보를 얻어올 수 있는 API 를 제공하자
- 클래스 필드에 대한 정보가 필요한 프로그래머는 toString 의 값을 파싱해야 한다.
→ 성능저하, 불필요한 작업
→ 향후 포맷을 바꾸면 시스템이 망가진다.
접근자를 제공하지 않으면, 변경될 수 있다고 문서화를 해도
그 포맷이 사실상 준-표준 API 나 다름없다.
# toString 을 재정의 하지 않아도 되는 타입
- 정적 유틸리티 클래스[4]
- 대부분의 열거타입[34]은 자바가 이미 완벽한 toString 을 제공
# toString 을 재정의 해야하는 타입
하위 클래스들이 공유해야 할 문자열 표현이 있는 추상클래스 ??
- 대다수의 컬렉션 구현체는 추상 컬렉션 클래스들의 toString 메서드를 상속해서 쓴다.
# toString 자동생성
AutoValue
프레임워크로는 클래스의 의미까지 파악하기 어렵다.- 자동생성에 적합하지 않는 타입
- PhoneNumber 은 표준체계가 있다.
- 자동생성에 적합하지 않더라도 객체의 값에 관해 아무것도 알려주지 않는 Object 의 toString 보다는 자동생성하는 것이 낫다.