Effective Java - Item 12
Updated:
Effective Java
Item 12. toString을 항상 재정의하라
toString을 재정의 해야 하는 이유
일반적으로 Object의 기본 toString 메서드는 클래스이름@16진수HashCode
를 반환한다.
이는 그다지 쓸모 있어 보이지 않는다.
toString의 일반 규약에 따르면 간결하면서 사람이 읽기 쉬운 형태의 유익한 정보 를 반환하라고 되어있다.
toString을 잘 구현한 클래스는 사용하기에 훨씬 편하고, 디버깅하기 쉽다.
그 이유는 println, printf, +, assert 와 같은 구문에 넘길때 자동으로 호출 되며 오류 메세지를 로깅할 때 자동으로 호출된다.
toString을 재정의하면 위와 같은 경우에서 유용하게 사용 할 수 있다.
따라서 toString의 또 다른 규약은 모든 하위 클래스에서 재정의하라! 라고 되어있다.
실전에서 toString은 그 객체가 가진 주요 정보 모두를 반환하는 게 좋다.
하지만 객체가 거대하거나 객체의 상태가 문자열로 표현하기에 적합하지 않다면 무리가 있다. 이러한 상황이면 요약 정보를 담아야 한다
EX) 전화번호부(총 1432434개)
or Thread[main,5,main]
마지막으로 하위 클래스들이 공유해야 할 문자열 표현이 있는 추상 클래스
라면 toString을 재정의 해야한다.
toString의 포멧
toString 메서드는 여러 곳에서 활용되는 만큼 재정의시 포멧을 명시해 주는 것이 좋다.
대신 포멧을 한번 명시하면 프로그래머들이 그 포멧에 맞춰 파싱하고(toString에서 필요한 데이터를 가져온다), 새로운 객체를 만들고 영속 데이터를 저장하는 등 평생 그 포멧에 얽매이게 된다.
또한 포맷을 바꾼다면 그에 따른 Side Effect가 발생하게된다는 단점이 존재한다.
따라서 포맷 명시 여부와 상관없이 toString이 반환한 값에 포함된 정보를 얻을 수 있는 API를 제공하자.
그렇지 않으면 이 정보가 필요한 프로그래머는 toString의 반환 값을 파싱할 수 밖에 없다.
게다가 향후 포맷을 바꾸면 시스템이 망가진다.
/**
* 이 전화번호의 문자열 표현을 반환한다.
* 이 문자열은 "XXX-YYY-ZZZZ" 형태의 12글자로 구성된다.
* XXX는 지역 코드, YYY는 프리픽스, ZZZZ는 가입자 번호다.
* 각각의 대문자는 10진수 숫자 하나를 나타낸다.
*
* 전화번호의 각 부분의 값이 너무 작아서 자릿수를 채울 수 없다면,
* 앞에서부터 0으로 채워나간다. 예를 들어 가입자 번호가 123이라면
* 전화번호의 마지막 네 문자는 "0123"이다.
*/
@Override
public String toString() {
return String.format("%03d-%03d-%04d",
areaCode, prefix, lineNum);
}
/**
* 이 약물에 관한 대락적인 설명을 반환한다.
* 다음은 이 설명의 일반적인 형태이나,
* 상세 형식은 정해지지 않았으며 향후 변경될 수 있다.
*
* "[약물 #9: 유형=사랑, 냄새=테레빈유, 겉모습=먹물]"
*/
@Override
public String toString() { ... }
toString을 재정의 하지 않아도 되는 경우
정적 유틸리티 클래스(item 4)는 toString을 제공할 이유가 없다. 또한 Enum타입도 java가 이미 완벽한 toString을 제공한다.
Google의 AutoValue 프레임워크는 toString도 생성해 준다.
AutoValue는 각 필드의 내용을 멋지게 나타내 주기는 하지만 클래스의 ‘의미’까지는 파악하지 못한다.
따라서 전화번호 클래스는 적합하지 않고(표준 체계를 따라야 하므로), 내용 성분만 나열해도 좋은 Potion 클래스는 적합하다!
정리
toString 규약
- 간결하면서 사람이 읽기 쉬운 형태의 유익한 정보를 반환하라.
- 모든 하위 클래스에서 이 메서드를 재정의하라.
- equals와 hashCode만큼 중요하진 않지만 잘 구현하면 사용하기 좋고 디버깅이 쉽다.
- 그 객체가 가진 주요 정보 모두를 반환하는게 좋다.
- 포맷을 명시하든 아니든 의도는 명확히 밝혀야 한다.
- toString이 반환한 값에 포함된 정보를 얻어올 수 있는 API를 제공하자.
출처
Joshua Bloch. Effective Java 3/E. n.p.: 인사이트, 2018년 11월 1일.
참고 페이지
https://icarus8050.tistory.com/70
https://dlsrb6342.github.io/2019/04/30/Effective-Java-3rd-ITEM-12/