ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 모든 객체의 공통 메서드 - 아이템 12. toString을 항상 재정의하라
    Study/Effective Java 2022. 12. 14. 14:38

    toString을 항상 재정의하라

    toString을 재정의해야 하는 이유

    1. toString() 메서드를 재정의하지 않은 클래스에서는 적합한 문자열을 반환하지 않는다.

    2. toString() 메서드를 재정의하지 않은 경우 "User@2d363fb3"와 같이 "클래스_이름@16진수로_표시한_해시코드"를 반환한다.

    3. "User{name='홍길동'}"과 같이 객체의 정보를 직접 알려주는 형태가 훨씬 유익하다.

    4. toString() 메서드를 잘 구현한 클래스는 사용하기에 훨씬 즐겁고, 해당 클래스를 사용한 시스템은 디버깅에 용이하다.

    5. 직접 호출하지 않더라도 println(), printf(), 문자열 연결 연산자(+), assert 구문에 넘길 때 혹은 디버거가 객체를 출력할 때 등 자동으로 불리는 경우가 많다.

     

    toString() 메서드를 재정의하지 않은 경우

    public class User {
        private String name;
    
        public User(String name) {
            this.name = name;
        }
    }

    위와 같이 User 클래스를 정의하였다.

     

    public class Main {
        public static void main(String[] args) {
            User user = new User("홍길동");
    
            System.out.println(user);
        }
    }

    위와 같이 User 객체를 생성하고 객체를 출력한다.

     

    User@2d363fb3

    toString() 메서드를 재정의하지 않았을 경우 출력 결과는 위와 같다.

     

    toString() 메서드를 재정의한 경우

    public class User {
        private String name;
    
        public User(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }

    User 클래스에 toString() 메서드를 정의하였다.

     

    public class Main {
        public static void main(String[] args) {
            User user = new User("홍길동");
    
            System.out.println(user);
        }
    }

    User 객체를 생성하고 객체를 출력한다.

     

    User{name='홍길동'}

    toString() 메서드를 재정의 한 경우 출력 결과는 위와 같다.

     

    toString을 재정의하는 방법

    1. 간결하면서 사람이 읽기 쉬운 형태의 유익한 정보를 담아야 한다.

    PhoneNumber@adbbd -> 012-1234-5678   
    Car@2d363fb3      -> Car{name=sun, position=2}

    위와 같이 간결하고 다른 사람이 읽기 쉬운 형태의 유익한 정보를 출력하도록 재정의 해야 한다.

     

    2. 객체가 가진 주요 정보 모두를 반환하는 게 좋다.

    public class Address {
        private final String city;
        private final String gu;
        private final String dong;
        private final String detail;
    
        public Address(String city, String gu, String dong, String detail) {
            this.city = city;
            this.gu = gu;
            this.dong = dong;
            this.detail = detail;
        }
    
        @Override
        public String toString() {
            return "Address{" +
                    "city='" + city + '\'' +
                    ", gu='" + gu + '\'' +
                    '}';
        }
    }

    위 Adress 클래스에 정의된 toString() 메서드와 같이 일부의 정보만을 반환하는 것은 좋은 방법이 아니다. 만약, 객체가 거대하거나 객체의 상태가 문자열로 표현하기 어렵다면 요약된 정보를 담아야 한다. ex) 맨해튼 거주자 전화번호부(총 1487536개)

     

    3. toString을 구현할 때면 반환 값의 포맷을 문서화할지 정해야 한다.

    @Override
    public String toString() {
        return String.format("%s-%s-%s", areaCode, prefix, lineNumber);
    }

    전화번호부나 행렬 같은 값 클래스라면 문서화를 권장한다. 포맷을 명시하면 객체는 표준이고, 명확하고, 사람이 읽을 수 있게 된다.

     

    /** 포맷 적용 전 */
    PhoneNumber(areaCode='02', prefix='512', lineNumber=1234');
    
    /** 포맷 적용 후 */
    02-512-1234

    포맷을 적용하기 전보다 적용한 후가 훨씬 더 간결하고 읽기 쉬운 것을 알 수 있다. 다만 포맷 명시에도 단점이 있다. 포맷을 하면 읽기 편하고 좋지만, 포맷을 한번 명시하면 평생 그 포맷에 얽매이게 된다. 즉 수정이 어렵다는 뜻이다. 반대로, 포맷을 명시하지 않는다면 향후 릴리스에서 정보를 더 넣거나 포맷을 개선할 수 있는 유연성을 얻게 된다.

     

    따라서, 포맷 명시 여부와 상관없이 toString() 메서드가 반환한 값에 포함된 정보를 얻어올 수 있는 API를 제공해야 한다. 접근자를 제공하지 않으면 이 정보가 필요한 프로그래머는 toString() 메서드의 반환 값을 파싱 해야 하는데, 이는 성능을 떨어뜨림과 동시에 불필요한 작업이고, 향후 포맷을 바꾸면 시스템이 망가지는 결과를 초래할 수 있다.

     

    toString을 재정의 하지 않아도 되는 경우

    toString() 메서드를 재정의하지 않아도 되는 경우는 정적 유틸리티 클래스이거나, 이미 toString() 메서드가 제공되는 Enum 타입이다.

     

    최종 정리

    모든 구체 클래스에서 Object의 toString() 메서드를 재정의하는 것이 좋다. 상위 클래스에서 이미 알맞게 재정의한 경우는 예외다. toString() 메서드를 재정의한 클래스는 사용하기도 즐겁고, 그 클래스를 사용한 시스템을 디버깅하기 쉽게 해 준다. 또한, toString() 메서드는 해당 객체에 관한 명확하고 유용한 정보를 읽기 좋은 형태로 반환해야 한다.


    출처

     이펙티브 자바 Effective Java 3/E. 조슈아 블로크 저자(글) · 개앞맵시(이복연) 번역

    https://github.com/woowacourse-study/2022-effective-java/blob/main/03%EC%9E%A5/%EC%95%84%EC%9D%B4%ED%85%9C_12/toString%EC%9D%84%20%ED%95%AD%EC%83%81%20%EC%9E%AC%EC%A0%95%EC%9D%98%ED%95%98%EB%9D%BC.md

     

    728x90

    댓글

Designed by Tistory.