맞는데 왜 틀릴까..?

Java/Effective Java

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

안도일 2023. 3. 9. 01:01

Object의 기본 toString 메서드가 우리가 작성한 클래스에 적합한 문자열을 반환하는 경우는 거의 없다. PhoneNumber@adbbd 처럼 단순히 클래스_이름@16진수로_표시한_해시코드를 반환할 뿐이다.

 

toString의 규약은 모든 하위 클래스에서 이 메서드를 재정의 하라고 한다.

 

toString은 프로그래머가 직접 호출하지 않더라도 println. printf, 문자열 연결 연산자(+), assert 구문에 넘길 때, 혹은 디버거가 객체를 출력할 때 등등 자동으로 불린다. 따라서 toString을 항상 재정의 해주자.

 

 

toString은 그 객체가 가진 주요 정보 모두를 반환하는게 좋다. 

만약 객체가 거대하거나 문자열로 표현하기 적합하지 않다면 요약 정보를 담자.

 


 

toString을 구현할 때 반환값의 포맷을 문서화할지 정해야 한다.  전화번호나 행렬 같은 값 클래스라면 아래와 같이 문서화하자.

 

 

이러한 문서화나 명시는 장점과 단점을 가지는데 한번 살펴 보자.

 

 

장점 1. 표준적이다.

 

포맷을 명시하면 그 객체는 표준적이고, 명확하고, 사람이 읽을 수 있게 된다. 따라서 그 값 그대로 입출력에 사용하거나 CSV 파일처럼 사람이 읽을 수 있는 데이터 객체로 저장할 수 도 있다.

 

장점 2. 문자열과 객체를 상호 전환할 수 있다.

 

명시된 포맷에 따라 객체를 문자열로 변환하면 그 반대의 작업인 문자열에서 객체로의 변환도 수행할 수 있다.

이때 정적 팩터리나 생성자를 사용하여 문자열을 인수로 받아 객체를 생성할 수 도 있다. 

아래 예를 살펴보자.

 

이름과 나이를 필드로 가지는 Person 클래스가 있다.

 

 

만약 문자열을 인수로 받아 문자열에서 이름과 나이를 추출하여 Person 객체를 생성하는 정적 팩터리 메서드를 만든다면 문자열과 객체를 상호 전환할 수 있다.

 

 

 

 

단점. 포맷을 명시한 클래스가 많이 쌓인다면 평생 그 포맷에 얽히게 된다.

 

이를 사용하는 프로그래머들이 명시한 포맷에 맞춰 여러 가지 작업들을 할 것인데 만약 향후에 포맷을 바꿔버린다면 이를 사용하던 코드들과 데이터들을 엉망이 될 것이다. 반대로 포맷을 명시하지 않는다면 향후에 정보를 더 넣거나 포맷을 개선할 수 있는 유연성을 얻게 된다.

 

 


주의할 점

 

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

 

정적 유틸리티 클래스는 toString을 제공할 이유가 없다.

 

대부분의 열거 타입은 자바가 이미 완벽한 toString을 제공하고 있다.