[자바] toString 을 항상 재정의하라

skyepodium·2021년 12월 26일
1
post-thumbnail

Object 클래스의 toString에 대해 알아봅시다.

혹시 그런적 있으신가요?

객체에 무엇이 들어있는지 확인하기 위해 System.out.println(); 으로 출력하려고했던 경험이

이러한 경우 대부분 원하는 결과를 알기 어렵습니다.

1. 예시

저에게 강아지가 있고, 자바 클래스로 정의하면 다음과 같습니다.

class Dog {
    // 이름을 저장하는 인스턴스 변수
    private String name;
    // 나이를 저장하는 인스턴스 변수
    private int age;

    // 생성자
    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

생성자를 통해 객체를 생성하고 잘 들어갔는지 출력하면,

class Main {
    public static void main(String[] args) {
        // 생성자를 통해 객체 생성
        Dog dog = new Dog("모카", 1);

        // 출력
        System.out.println(dog);
    }
}

의미를 파악하기 어려운 문자열이 출력됩니다.

하나씩 알아봅시다.

참고

예를 위해 객체System.out.println으로 출력하는 예를 들었습니다. 실제로는 이렇게 하면 정말 레알로 욕 엄청 먹습니다. 제가 그랬습니다.

  1. 디버깅 목적 - IDE의 디버그 모드를 사용합니다. (출력보다, 이게 훨씬 좋습니다.)
  2. 로깅 목적 - 프로젝트에서 사용하고 있는 로깅 모듈을 사용합니다.(log4j, slf4j 등등)

2. toString

1) System.out.println

객체를 println으로 출력한다고 하면

우선println 메서드는 String.valueOf 메서드를 통해 파라미터로 받은 객체를 문자열로 변환합니다.

String.valueOf 메서드는 Object의 toString() 메서드를 호출해서 문자열을 반환합니다.

그래서..응? 난 toString() 메소드 만든적 없는데..

모든 클래스는 Object 클래스를 기본적으로 상속받고, Object 클래스에 toString 메서드를 가지고 있습니다.

3. Object의 toString

Object 클래스의 toString을 열어보면 다음과 같습니다.

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

클래스 이름 + '@' + 해시코드 16진수 이에 따라 예시와 같은 Dog@1134affc 문자열이 출력됩니다.

hashCode 메서드는 객체 멤버변수의 값을 이용해서 특정한 고유한 hash를 반환하는 메서드입니다.

자세한 내용은 다음을 참고해주세요.
[자바] equals, hashCode는 낯설어서

자 그래서, 이펙티브 자바에 따르면 이렇게 되어있습니다.

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

우리도 재정의해봅시다.

4. toString 재정의

참고에서도 말했지만, 객체를 문자열로 찍는 것은 로깅을 위한 목적이 제일 큽니다. (내부적으로 값 잘 들어있는지 검사하기 위해서는 IDE의 디버깅 기능을 사용합니다.)

로깅을 하는 프로젝트라면, 로깅 규칙 까지 정의되어있을 가능성이 큽니다.

다만, 우리는 그냥 잘 들어있는지 찍어보는것이니까 규칙도 없고, 인텔리제이 IDE의 기능을 사용해서 만들면 다음과 같습니다.

class Main {
    public static void main(String[] args) {
        // 생성자를 통해 인스턴스 생성
        Dog dog = new Dog("모카", 1);

        // 출력
        System.out.println(dog);
    }
}

class Dog {
    // 이름을 저장하는 인스턴스 변수
    private String name;
    // 나이를 저장하는 인스턴스 변수
    private int age;

    // 생성자
    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    // 인텔리제이의 generate 기능을 사용했습니다.
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

오 이제 어떤 값이 들어있는지 잘 출력됩니다.

5. 정리

모든 구체 클래스에서 Object의 toString 재정의합니다.
(이미 알맞게 재정의되어있는 경우는 제외)

6. 참고

이펙티브 자바 - toString을 항상 재정의하라 (아이템 12)

profile
callmeskye

0개의 댓글