💡 모든 클래스에서
Object
의toString
을 재정의하자. (상위 클래스에서 재정의한 경우 빼고!)
재정의한toString
은 객체에 대해 사람이 읽기 쉬운 짧지만 유익한 정보를String
형태로 반환해야 한다.
toString
이란?Java 11 API에서 Object
의 toString
메서드의 정의를 찾아보면 다음과 같다.
public String toString()
Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method.
The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:
getClass().getName() + '@' + Integer.toHexString(hashCode())
Returns:
a string representation of the object.
요약하자면, toString
메서드는 객체에 대해 사람이 읽기 쉬운 짧지만 유익한 정보를 String
형태로 반환하는 메서드이다. 또한, Object
의 모든 하위 클래스가 해당 메서드를 재정의하도록 권고하고 있다.
만약 재정의되지 않았다면, toString
메서드는 클래스_이름@16진수_해시코드
형태의 결과를 반환한다.
toString
을 재정의해야 하는 이유
toString
을 재정의한 클래스는 디버깅하기 쉽다.
toString
메서드는 println
, printf
, assert
구문에 넘기거나 디버거가 객체를 출력할 때 자동으로 불린다.
System.out.println(phoneNumber + "에 연결할 수 없습니다.");
toString
을 재정의하지 않은 경우, 출력 결과는 다음과 같을 것이다.
PhoneNumber@adbbd에 연결할 수 없습니다.
제대로 재정의했다면, println
구문은 더 의미 있는 결과를 반환한다.
@Override
public String toString() {
return "PhoneNumber(owner=" + owner + ", phoneNumber=" + phoneNumber + ")");
// 출력 결과
PhoneNumber(owner=Jenny, phoneNumber=01012341234)에 연결할 수 없습니다.
toString
을 재정의할 때 지켜야 할 점TelephoneBook(area=Massachusetts, entryCount=147865)
BigDecimal
, BigInteger
// BigDecimal에서 String, String에서 BigDecimal을 상호 전환 가능하다.
BigDecimal bd1 = new BigDecimal("-10.01");
String bdString = bd1.toString();
BigDecimal bd2 = new BigDecimal(bdString);
toString
을 재정의할 때 주의할 점toString
를 재정의할 때, 포맷을 명시한다면, 해당 포맷에 계속 얽매일 수도 있다.toString
포맷에 맞춰 파싱, 객체 생성, DB 저장하는 등의 코드를 작성하게 될 가능성이 높기 때문이다.toString
재정의 시 프로그래머의 의도를 명확히 밝히자. (Javadoc에 쓰란 얘기인 것 같다.)/**
* 이 전화번호의 문자열 표현을 반환한다.
* 이 문자열은 "XXX-YYY-ZZZZ" 형태의 12글자로 구성된다.
* XXX는 지역 코드, YYY는 프리픽스, ZZZZ는 가입자 번호다.
* 각각의 대문자는 10진수 숫자 하나를 나타낸다.
*
* 전화번호의 각 부분의 값이 너무 작아서 자릿수를 채울 수 없다면,
* 앞에서부터 0으로 채워나간다. 예컨대 가입자 번호가 123이라면
* 전화번호의 마지막 네 문자는 "0123"이 된다.
*/
@Override
public String toString() {
return String.format("%03d-%03d-%04d", areaCode, prefix, lineNum);
}
/**
* 이 약물에 관한 대략적인 설명을 반환한다.
* 다음은 이 설명의 일반적인 형태이나,
* 상세 형식은 정해지지 않았으며 향후 변경될 수 있다.
*
* "[약물 #9: 유형=사랑, 냄새=테레빈유, 겉모습=먹물]"
*/
@Override
public String toString() { ... }
toString
이 반환한 값에 포함된 정보를 얻어올 수 있는 API를 제공하자.toString
의 결과로 나온 String
을 굳이 파싱하지 않아도 해당 인스턴스의 값을 사용할 수 있도록 getter를 제공하자.toString
결과값에 의존적이므로 유연하지 않다.toString
이 필요 없는 경우toString
을 제공할 이유가 없다.toString
이 제공된다.반대로 하위 클래스가 있는 추상 클래스라면, toString
을 재정의해줘야 한다.
toString
자동 생성하는 법@AutoValue
annotation을 사용하면, 알아서 몇몇 메서드와 변수를 생성해주는데, toString
도 있다. 튜닝이 필요할 수 있지만, Object
에 기본 정의된 toString
보다는 낫다.@Data
, @ToString
@Data
는 @ToString
외에도 @Getter
, @Setter
등을 포함한 메서드를 자동 생성해준다.toString
메서드에서 제외하고 싶은 것이 있다면 위에 @ToString.Exclude
, 포함하고 싶은 것이 있다면 @ToString.Include
annotation을 사용하면 된다.