이 글은 Effective Java 3/E의 내용을 요약한 글입니다. 자세한 내용은 책을 참고하시기 바랍니다.
toString 메서드
Object의 기본 toString메서드는 기본적으로 클래스 이름@16진수로 표현한 해시코드
를 반환합니다.
실제로 Object.java파일의 toString메서드를 보면 다음과 같습니다.
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
위의 메서드를 보면 처음 말한바와 같이 클래스 이름@16진수로 표현한 해시코드
을 return 하는 것을 확인할 수 있습니다.
테스트를 해보면 다음과 같습니다.
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
테스트 결과를 보면 Car를 출력하였을 때 Car@6b71769e
라는 결과가 나온 것을 확인할 수 있습니다. 하지만 이러한 형태의 문자열은 일반적으로 우리가 원하는 결과가 아니고 정보를 얻을 수 있는 좋은 정보도 아닙니다.
toString의 일반 규약을 보면 "간결하면서 사람이 읽기 쉬운 형태의 유익한 정보를 반환해야한다."와 "모든 하위 클래스에서 이 메서드를 재정의하라"라고 합니다. 따라서 우리는 toString이 유익한 정보를 반환하도록 재정의해줘야 합니다.
여기서 모든 클래스에서 toString을 재정의하라는 것은 도대체 왜 그런 걸까요?
그것은 바로 디버깅을 위해서 입니다. toString메서드는 우리가 따로 호출하지 않더라도 오류가 발생하여 로깅할 때와 같이 자동으로 호출되기도 합니다.
만약 toString을 재정의 하지 않고 Car@6b71769e
와 같은 결과만을 본다면 해당 메시지는 쓸모 없는 메시지가 될 것이라 꼭 toString을 재정의하여야 한다는 것입니다.
toString 재정의하기
- 좋은 toString 재정의를 하려면 객체가 가진 모든 정보를 반환하는 것이 좋다.
- 만약 객체가 가진 정보(필드)가 너무 거대하거나 객체의 상태가 문자열로 표현하기에 적합하지 않다면 요약 정보를 담아 출력을 하도록 한다.
-
구현을 할 때는 포맷을 문서화할지 정해야한다.
- 포맷을 문서화하면 해당 객체는 표준적이고, 명확하고, 사람이 읽기 쉽게 된다.
- 전화번호 같이
000-0000-0000
와 같은 것은 포맷을 문서화하는 것이 좋다. - 하지만 포맷을 명시하면 해당 클래스는 앞서 정의한 포맷에 얽매이게 된다.
- 프로그래머들이 해당 문자열을 파싱해서 데이터를 사용한다면, 포맷 값이 변화하면 관련 내용들이 모두 변경되게 된다.
- 포맷을 명시하지 않는다면 향후 정보를 더 넣거나 포맷을 개선할 수 있는 유연성을 얻게 된다.
-
포맷을 명시하든 아니든 의도는 명확히 밝혀야한다.
- 포맷을 명시한다면 포맷에 대한 정보까지 주석으로 남겨두는 것이 좋고, 포맷을 명시하지 않는다면 형식이 변경될 수 있다고 명시해야한다.
하지만 toString으로 반환되는 값을 통해 로직을 작성하는 것은 좋지 않아 사용하지 않는 것이 좋다!! 그 대신 해당 정보를 얻어올 수 있는 API를 제공해야한다. 즉, getter를 통해 개발자들이 필요한 정보를 얻어 올 수 있도록 하는 것이 좋다.
핵심 정리
모든 구체 클래스에서 Object의 toString을 재정의하자. 상위 클래스에서 이미 알맞게 재정의한 경우는 예외다. toString을 재정의한 클래스는 사용하기에도 즐겁고 그 클래스를 사용한 시스템을 디버깅하기 쉽게 해준다. toString은 해당 객체에 관한 명확하고 유용한 정보를 읽기 좋은 형태로 반환해야 한다.
Add
우아한 테크코스 Level1의 1단계 미션을 진행하며 다음과 같은 피드백을 받았습니다.
Domain에 toString을 재정의하여 OutputView에서 System.out.println(car)
와 같이 사용을 하다보니 domain과 view의 관계가 엮이게 되었습니다.
즉, view의 출력 결과를 변경하려면 domain을 변경해야하는 문제점이 생긴 것입니다.
여기서 다시 알 수 있는 것은 MVC패턴에서 toString재정의한 내용을 view에서 사용하면 model과 view의 관계가 엮이게 된다는 문제가 생긴다는 것을 알 수 있습니다.
toString으로 반환되는 값을 통해 로직을 작성하는 것은 좋지 않아 사용하지 않는 것이 좋다(remind)❗️❗️ 하지만 디버깅을 위해 toString의 재정의는 꼭 하자❗️❗️