Object 클래스의 toString에 대해 알아봅시다.
객체에 무엇이 들어있는지 확인하기 위해 System.out.println();
으로 출력하려고했던 경험이
이러한 경우 대부분 원하는 결과를 알기 어렵습니다.
저에게 강아지가 있고, 자바 클래스로 정의하면 다음과 같습니다.
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
으로 출력
하는 예를 들었습니다. 실제로는 이렇게 하면 정말 레알로 욕 엄청 먹습니다. 제가 그랬습니다.
객체를 println으로 출력한다고 하면
우선println
메서드는 String.valueOf
메서드를 통해 파라미터로 받은 객체를 문자열로 변환합니다.
String.valueOf
메서드는 Object의 toString() 메서드를 호출해서 문자열을 반환합니다.
그래서..응? 난 toString() 메소드 만든적 없는데..
모든 클래스는 Object 클래스
를 기본적으로 상속
받고, Object 클래스에 toString 메서드
를 가지고 있습니다.
Object 클래스의 toString을 열어보면 다음과 같습니다.
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
클래스 이름 + '@' + 해시코드 16진수
이에 따라 예시와 같은 Dog@1134affc
문자열이 출력됩니다.
hashCode 메서드는 객체 멤버변수의 값을 이용해서 특정한 고유한 hash를 반환하는 메서드입니다.
자세한 내용은 다음을 참고해주세요.
[자바] equals, hashCode는 낯설어서
자 그래서, 이펙티브 자바에 따르면 이렇게 되어있습니다.
모든 구체 클래스에서 Object의 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 +
'}';
}
}
오 이제 어떤 값이 들어있는지 잘 출력됩니다.
모든 구체 클래스에서 Object의 toString 재정의합니다.
(이미 알맞게 재정의되어있는 경우는 제외)
이펙티브 자바 - toString을 항상 재정의하라 (아이템 12)