관리 메뉴

백엔드 개발자 블로그

[Effective Java] Item12. toString을 항상 재정의하라 본문

Java

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

backend-dev 2024. 4. 4. 22:46

toString 재정의 해야하는 이유

Object의 기본 toString메서드는 기본적으로 클래스 이름@16진수로 표현한 해시코드를 반환합니다.

실제로 Object.java파일의 toString메서드를 보면 다음과 같습니다.

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

 

실제로 Car를 출력하였을 때 Car@6b71769e라는 결과가 나온 것을 확인할 수 있습니다.

public class Car {
  private String name;
  private int position;
}
public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        System.out.println(car);
    }
}
// 출력 결과 : Car@6b71769e

 

하지만 일반 규약에도 위반되고 정보를 얻을 수 있는 좋은 정보도 아닙니다. 그래서 toString을 재정의해야합니다.

일반규약

  • 간결하면서 사람이 읽기 쉬운 형태의 유익한 정보를 반환해야한다.
  • 모든 하위 클래스에서 이 메서드를 재정의하라

toString 재정의하기

  • 좋은 toString 재정의를 하려면 객체가 가진 모든 정보를 반환하는 것이 좋습니다.
  • 만약 객체가 가진 정보(필드)가 너무 거대하거나 객체의 상태가 문자열로 표현하기에 적합하지 않다면 요약 정보를 담아 출력을 하도록 합니다.
  • 구현을 할 때는 포맷을 문서화할지 정해야합니다.
    • 포맷을 문서화하면 해당 객체는 표준적이고, 명확하고, 사람이 읽기 쉽게 됩다.
    • 전화번호 같이 000-0000-0000와 같은 것은 포맷을 문서화하는 것이 좋습니다.
    • 하지만 포맷을 명시하면 해당 클래스는 앞서 정의한 포맷에 얽매이게 됩니다.
    • 프로그래머들이 해당 문자열을 파싱해서 데이터를 사용한다면, 포맷 값이 변화하면 관련 내용들이 모두 변경되게 됩니다.
    • 포맷을 명시하지 않는다면 향후 정보를 더 넣거나 포맷을 개선할 수 있는 유연성을 얻게 됩니다.
  • 포맷을 명시하든 아니든 의도는 명확히 밝혀야합니다.
    • 포맷을 명시한다면 포맷에 대한 정보까지 주석으로 남겨두는 것이 좋고, 포맷을 명시하지 않는다면 형식이 변경될 수 있다고 명시해야합니다.

 

주의사항

toString으로 반환되는 값을 통해 로직을 작성하는 것은 좋지 않아 사용하지 않는 것이 좋습니다

그 대신 getter를 통해 개발자들이 필요한 정보를 얻어 올 수 있도록 하는 것이 좋습니다.

view의 출력 결과를 변경하려면 domain을 변경해야하는 문제점이 생기기 때문입니다.

예시

실제로 지인이 다음과 같은 피드백을 받은 적이 있습니다.

 

Domain에 toString을 재정의하여 OutputView에서 System.out.println(car)와 같이 사용을 하다보니 domain과 view의 관계가 엮이게 되었습니다. 즉, view의 출력 결과를 변경하려면 domain을 변경해야하는 문제점이 생긴 것입니다. 그러므로 toString으로 반환되는 값을 통해 로직을 작성하지 맙시다.


핵심 정리

  • 모든 구체 클래스에서 Object의 toString을 재정의하자. (상위 클래스에서 이미 알맞게 재정의한 경우는 예외다.)
  • toString은 해당 객체에 관한 명확하고 유용한 정보를 읽기 좋은 형태로 반환하여 디버깅하기 쉽게 해줘야 한다.
  • toString으로 반환되는 값을 통해 로직을 작성하지 말자. (view의 출력 결과를 변경하려면 domain을 변경해야하는 문제점이 생긴다.)