2017년 5월 10일 수요일

effective java 규칙 10. toString 은 항상 재정의하라

규칙을 설명하기 전에 toString 의 목적을 알아보자.
toString 메서드의 목적은 객체의 정보를 문자화 시키는데 있다.
여기서 객체의 정보란 인스턴스 변수에 저장된 값을 뜻한다.

우리는 이러한 toString() 를 사용함으로써 logging 등에 유용하게 사용할 수 있다.
이외의 용도는 논의 할 필요성이 있다. 
임의의 비즈니스 로직에서 객체의 toString 결과를 사용하는 코드가 필요한지는 의문이 든다. 
(비즈니스를 처리하는 로직은 별도의 메소드를 만들어 처리해야 할 것 같다.)


이렇게 객체의 정보를 문자화 시키는 Object 클래스의 toString public method 는 다음과 같이 정의되어 있다.

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

기본 결과 형태가 나타내는 정보는 위의 정의에서 나타나듯이 해당 클래스의 이름 + @ (구분자) +  hashCode 형태이다.
이 결과로 얻을수 있는 유용한 정보는 객체의 클래스 명 정도이다.
hashCode 는 이전 규칙( rule 9) 에서 언급 했듯이 hash 알고리즘으로 계산된 결과이고
같은 객체에 대해선 같은 hashCode 가 보장되지만 다른 객체에선 항상 다른 hashCode 값이 보장이 되지 않으므로 객체의 식별자 역할을 하기에는 부족하다. (참고용 정도?)

그렇기 때문에 toString method 를 객체가 가지고 있는 인스턴스 변수를 표현하도록 override 해야 한다.

이쯤에서 toString() 의 일반규약을 알아보자.
1. 사람이 읽기 쉽도록 간략하지만 유용한 정보를 제공
2. 모든 하위 클래스는 이 메서드를 재정의함이 바람직하다.

위와 같은 일반규약을 가지고 있고 책(effective java) 에서는 객체 내의 중요 정보를 전부 담아 반환 (많을 경우 요약정보로 반환) 하는 것을 권장한다.

그리고 저자는 toString 구현시 그 포멧을 문서에 명시하는 것에 대해 설명하고 있고 
(예:bigInteger, BigDecimal 등 boxing class.. / 그리고 값 클래스는 형식 명시 권장함)
형식을 명시 하지 않을 경우에도 (명시 할 때도 마찬가지로) 그 의도는 문서에 남겨야 한다고 한다.
(이런 입장 역시 -내 생각과는 다르게- toString 의 활용처를 좀더 넓게 보고 있는 것이다.)

의도를 문서에 남기는 것은 로깅시에도 필요한 경우가 많기 때문에 동의할 수 있는 부분이다.
하지만 포멧을 지정한다는 (주석으로 명시 한다는 문제가 아니라 비즈니스 로직에 사용하기 위해 포멧을 지정 한다는) 것은
내 개발 스타일에는 맞지 않는 것 같다.

그리고 toString 이 반환하는 정보는 별도의 접근자 (method 등.. getter)를 가져야 한다.
그렇지 않으면 해당 클래스를 사용하는 프로그래머는 toString 을 파싱해서 정보를 가져오도록 시도할 것이다.
(toString()  이 api 화됨)
이런 시도는 성능상에 불이익 및 오류등 안전하지 못한 시스템을 만들 가능성이 높아진다.
- 생각해 볼 문제 : 
그렇다면 클라이언트 코드에서 사용하지 못하도록 private 선언한 변수는 toString 에서 그 정보가 나타나지 않도록 해야 하는가?
그 정보가 로깅에 중요한 정보라도? - 협업의 공통 rule 로써 관리해야 할 것 같다. toString 의 활용법 제한등

- toString method 호출
* print 관련 메서드에서 객체를 사용할 때  (println, printf 등..)
System.out.println(c);


* 문자열 연결 연산자의 피 연산자로 사용될 때
String c = "a"+t;


* assert 구문이 실행될때
※ assert는 특정조건이 참일 때만 프로그램이 계속된다.
이러한 assert 구문은 java 실행시 vm option 에 -ea 를 주어야 적용된다.

assert c==null : t;

* 디버거에 객체가 전달될때


위와 같은 경우에 객체의 toString 메서드가 자동 호출 된다.


댓글 없음:

댓글 쓰기

Intelij 설정 및 plugin

1. preferences... (settings...) Appearance & Behavior > Appearance - Window Options        ✓   Show memory indicator Editor &...