[Java][Effective Java] item 12. toString을 항상 재정의하라

2022. 6. 13. 11:34JAVA/Effective Java

1. toString의 규약

  • toString의 규약은 "모든 하위 클래스에서 이 메서드를 재정의하라"입니다.

 

2. toString을 재정의 해야하는 이유는 무엇인가?

  • toString을 재정의함으로써 인스턴스 자체를 참조할때 인스턴스 멤버에 대한 정보를 표시할 수 있기 때문이다.
  • toString을 재정의하지 않으면 인스턴스를 출력시 클래스_이름@16진수로_표시한_해시코드를 반환할 뿐이다.
  • toString을 재정의한 클래스를 사용하는 시스템은 디버깅이 쉽게 됩니다.
  • 인스턴스를 참조하는 컴포넌트가 오류 메시지를 로깅(logging)할때 자동으로 호출하는데 이때 메시지에 유용한 로그를 남길 수 있습니다.

 

3. toString 구현시 문서화

  • toString을 구현할 때 반환값의 포맷을 문서화할지 정애야 합니다.
  • 명시한 포맷에 맞는 문자열과 객체를 상호 전환할 수 있는 정적 팩토리나 생성자를 함께 제공해주면 좋습니다.
  • toString 문서화의 단점은 포맷을 한번 명시하면 평생 그 포맷에 얽매이게 됩니다.

다음은 PhoneNumber 클래스의 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);
	}
	public static void main(String[] args) {
        PhoneNumber jenny = new PhoneNumber(707, 867, 5309);
        System.out.println("제니의 번호: " + jenny);
	}
제니의 번호: 707-867-5309

 

4. toString 재정의시 주의사항

  • 문서화시 포맷을 명시하든 아니든 의도는 명확히 밝혀야 합니다.
  • toString이 반환 값에 포함된 정보를 얻어올 수 있는 API를 제공해야 합니다.
    • 예를 들어 PhoneNumber 클래스는 지역코드, 프리픽스, 가입자 번호 멤버가 있는데 이 멤버들에 대한 접근자 getter를 제공해야 합니다. 그렇지 않으면 이 정보가 필요한 개발자는 toString의 반환값을 파싱할 수밖에 없습니다.
  • 정적 유틸리티 클래스는 toString을 제공할 이유가 없습니다.
  • 대부분의 열거 타입도 자바가 이미 완벽한 toString을 제공하니 따로 재정의하지 않아도 됩니다.

 

핵심 정리

모든 구체 클래스에서 Object의 toString을 재정의하자. 상위 클래스에서 이미 알맞게 재정의한 경우는 예외다. toString을 재정의한 클래스는 사용하기도 즐겁고 그 클래스를 사용한 시스템을 디버깅하기 쉽게 해준다. toString은 해당 객체에 관한 명확하고 유용한 정보를 읽기 좋은 형태로 반환해야 한다.

 

References

source code : https://github.com/yonghwankim-dev/effective_java/tree/master/src/role12
effective java 3/E