이펙티브 자바 - item 12. toString을 항상 재정의하라

item 12. toString을 항상 재정의하라

이펙티브 자바 - item 12. toString을 항상 재정의하라

모든 구체 클래스에서 Object의 toString을 재정의하자.

toString을 재정의하지 않으면 Object의 기본 toString 메서드를 사용하게 된다.Object 클래스의 toString을 열어보면 다음과 같다.


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

// 예시
System.out.println(phoneNumber); //PhoneNumber@1134affc (클래스이름@16진수로 표현한 해시코드)

간결하면서 사람이 읽기 쉬운 형태의 유익한 정보를 반환하기 위해서는 toSring 메서드를 재정의해야한다. 따라서 toString은 모든 구체클래스에서 재정의되어야 한다.

@Override public String toString() {
    return String.format("%03d-%03d-%04d",
            areaCode, prefix, lineNum);
}

//예시
System.out.println(phoneNumber); //PhoneNumber@010-****-1993

주의

  1. 포맷을 명시하든 아니든 개발자는 의도를 명확히 밝혀야 한다.
/**
* 이 전화번호의 문자열 표현을 반환한다.
* 이 문자열은 "XXX-YYY-ZZZZ" 형태의 12글자로 구성된다.
* XXX는 지역코드, YYY는 프리픽스, ZZZZ는 가입자 번호다.
* 각각의 대문자는 10진수 숫자 하나를 나타낸다.
*
* 전화번호의 각 부분의 값이 너무 작아서 자릿수를 채울 수 없다면,
* 앞에서부터 0으로 채워나간다. 예컨데 가입자 번호가 123이라면
* 전화번호의 마지막 네 문자는 "0123"이 된다.
*/
@Override
public String toString() {
    return String.format("%03d-%03d-%04d", areaCode, prefix, lineNum);
}
  1. toString이 반환한 값에 포함된 정보를 얻어올 수 있는 API를 제공하자.

어차피 toString으로 노출한 정보들은 외부에 노출되어 있으니, 각 필드를 따로 따로 조회할 수 있는 API(ex.Getter)를 만들어두자는 내용이다. 만약 만들지 않는다면, 클라이언트 입장에서 문자열을 파싱해서 써야 한다.

toString 재정의가 필요 없는 경우

정적 유틸리티 클래스 열거 타입 : 이미 완벽한 toString 제공

참고) JPA에서 순환참조를 조심하자

jpa에서 Member와 Team이 다대일 양방향 관계일 때를 생각해보자.

@ToString
public class Team {

    @Id
    @GeneratedValue
    private Long id;
    private String teamName;
    @OneToMany(mappedBy = "user")
    private Set<Member> users;
}
// @ToString -> 순환참조 가능
@ToString(exclude = "team")
public class Member {

    @Id
    @GeneratedValue
    private Long id;
    private String userName;
    @ManyToOne
    private Team team;
}

만약 Member의 toString를 호출하면 Team의 toString이 호출되고 또 다시 Member의 toString이 호출되어 스택오버플로우가 발생한다.

lombok의 @toString 을 남발하지 말고, 만약 사용한다면 exclude 조건 추가하자. @ToString(exclude = “team”) 또는 직접 toString을 구현해 순환참조를 방지해야 한다.

정리

모든 구체 클래스에서 Object의 toString을 재정의하자. 상위 클래스에서 이미 알맞게 재정의한 경우는 예외이다.

toString은 해당 객체에 관한 명확하고 유용한 정보를 읽기 좋은 형태로 반환 해주자