이펙티브 자바 아이템 12. toString은 항상 재정의 하라. Object의 toString은 우리에게 필요한 정보는 보이는것이 아니라 클래스이름@16진수 해시코드를 반환할뿐이다.
equals와 hashcode 처럼 대단히 중요하진 않지만 toString은 항상 재정의 하는것이 좋다.
그럼 PhoneNumber클래스를 보겠다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 package com.github.sejoung.codetest.tostring;public final class PhoneNumber { private final short areaCode, prefix, lineNum; public PhoneNumber (int areaCode, int prefix, int lineNum) { this .areaCode = rangeCheck(areaCode, 999 , "지역코드" ); this .prefix = rangeCheck(prefix, 999 , "프리픽스" ); this .lineNum = rangeCheck(lineNum, 9999 , "가입자 번호" ); } private static short rangeCheck (int val, int max, String arg) { if (val < 0 || val > max) throw new IllegalArgumentException(arg + ": " + val); return (short ) val; } @Override public boolean equals (Object o) { if (o == this ) return true ; if (!(o instanceof PhoneNumber)) return false ; PhoneNumber pn = (PhoneNumber) o; return pn.lineNum == lineNum && pn.prefix == prefix && pn.areaCode == areaCode; } @Override public int hashCode () { int result = Short.hashCode(areaCode); result = 31 * result + Short.hashCode(prefix); result = 31 * result + Short.hashCode(lineNum); return result; } public static void main (String[] args) { PhoneNumber jenny = new PhoneNumber(707 , 867 , 5309 ); System.out.println("제니의 번호: " + jenny); } }
실행 결과
1 2 3 4 5 제니의 번호: com.github.sejoung.codetest.tostring.PhoneNumber@adbbd Process finished with exit code 0
위에는 toString을 재정의 하지 않았을때 PhoneNumber@adbbd 라는 결과 값만 찍혔다.
toString을 정의할때 유이사항
toString은 그 객체가 가진 주요 정보 모두를 반환하는것이 좋다.
포멧을 명시하던 안하던 의도를 명확히 발혀야 된다.
포멧 명시 여부와 상관 없이 toString이 반환한 값에 포함된 정보를 얻어올수 있는 API를 제공하자.
PhoneNumber의 toString을 재정의 하는 부분
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 package com.github.sejoung.codetest.tostring;public final class PhoneNumber { private final short areaCode, prefix, lineNum; public PhoneNumber (int areaCode, int prefix, int lineNum) { this .areaCode = rangeCheck(areaCode, 999 , "지역코드" ); this .prefix = rangeCheck(prefix, 999 , "프리픽스" ); this .lineNum = rangeCheck(lineNum, 9999 , "가입자 번호" ); } private static short rangeCheck (int val, int max, String arg) { if (val < 0 || val > max) throw new IllegalArgumentException(arg + ": " + val); return (short ) val; } @Override public boolean equals (Object o) { if (o == this ) return true ; if (!(o instanceof PhoneNumber)) return false ; PhoneNumber pn = (PhoneNumber) o; return pn.lineNum == lineNum && pn.prefix == prefix && pn.areaCode == areaCode; } @Override public int hashCode () { int result = Short.hashCode(areaCode); result = 31 * result + Short.hashCode(prefix); result = 31 * result + Short.hashCode(lineNum); return result; } @Override public String toString () { return String.format("%03d-%03d-%04d" , areaCode, prefix, lineNum); } public static void main (String[] args) { PhoneNumber jenny = new PhoneNumber(707 , 867 , 5309 ); System.out.println("제니의 번호: " + jenny); } }
실행 결과
1 2 3 4 5 제니의 번호: 707-867-5309 Process finished with exit code 0
유틸클래스와 enum 클래스는 toString을 재정의 할필요 없다 enum은 자바에서 toString을 제공해준다.
참조