본문 바로가기

개발/이펙티브 자바

Effective Java ( 이펙티브 자바 ) - 아이템 12

toString을 항상 재정의하라


Object의 기본 toString 메서드가 우리가 작성한 클래스에 적합한 문자열을 반환하는 경우는 거의 없다. PhoneNuber@adbbd 처럼 단순히 클래스_이름@16진수로_표시한_해시코드 를 반환할 뿐이다. toString 일반 규약에 따르면 '간결하면서 사람이 읽기 쉬운 형태의 유익한 정보' 를 반환해야 한다. 또한 toString의 규약은 "모든 하위 클래스에서 이 메서드를 재정의하라"고 한다. 정말 새겨들어야 할 조언이다!

 

 equals, hashCode 규약만큼 대단히 중요하진 않지만, toString을 잘 구현한 클래스는 사용하기에 훨씬 즐겁고, 디버깅하기 쉽다. toString 메서드는 객체를 println, printf, 문자열 연결 +, assert 구문에 넘길 때, 자동으로 불린다.

 

실전에서 toString은 그 객체가 가진 주요 정보 모두를 반환하는 게 좋다. PhoneNumber라면 전화번호처럼 말이다. 하지만 객체가 거대하거나 객체의 상태가 문자열로 표현하기에 적합하지 않다면 무리가 있다. 이런 상황이라면 "맨해튼 거주자 전화번호부(총 1487536개)" 같은 요약 정보를 담아야 한다. 

 

  포맷을 문서화하여서, 표준적이고, 명확하고, 사람이 읽을 수 있게하는 것도 좋다. 단점도 있다. 포맷을 한번 명시하면 (그 클래스가 많이 쓰인다면 ) 평생 그 포맷에 얽매이게 된다. 이를 사용하는 프로그래머들이 그 포맷에 맞춰 파싱하고, 새로운 객체를 만들고, 영속 데이터로 저장하는 코드를 작성할 것이다.

 

  포맷을 명시하든 아니든 여러분의 의도는 명확히 밝혀야 한다. 명시하려면 아주 정확하게 해야 한다. 

 

  포맷 명시 여부와 상관없이 toString이 반환한 값에 포함된 정보를 얻어올 수 있는 API를 제공하자. 예를 들어, PhoneNumber 클래스는 지역 코드, 프리픽스, 가입자 번호용 접근자를 제공해야 한다. 그렇지 않으면 이 정보가 필요한 프로그래머는 toString 의 반환값을 파싱할 수 밖에 없다. 접근자를 제공하지 않으면 그 포맷이 사실상 준 표준 API나 다름없어진다.

 

  아이템 10에서 소개한 구글의 AutoValue 프레임워크는 toString도 생성해 준다 ( 대부분의 IDE도 마찬가지 ). 하지만 클래스의 '의미'까지 파악하지는 못한다. 그래도, 아무것도 알려주지 않는 Object의 toString보다는 자동 생성된 toString이 훨씬 유용하다.

 

모든 구체 클래스에서 Object의 toString을 재정의하자. toString을 재정의한 클래스는 사용하기도 즐겁고 디버깅하기 쉽게 해준다. 명확하고 유용한 정보를 읽기 좋은 형태로 반환해야 한다.