개요
Rest API를 통해 반환받은 Java Object를 로그로 찍어보는데 예상과 달리 "패키지명@난수"와 같은 형태로 출력되는 문제가 발생했습니다.
다행히도 stackoverflow에 이와 관련되어 잘 정리된 글이 있어 해당 내용을 정리해보고자 합니다.
배경지식
모든 Java 객체에는 객체를 출력할 때 호출되는 toString() 메서드가 있습니다.
System.out.println(myObject); // myObject.toString()를 호출
이 메서드는 Object 클래스(모든 Java 객체의 슈퍼 클래스)에 정의되어 있습니다.
Object.toString() 메서드는 클래스 이름, @ 기호 및 16진수로 구성된 상당히 보기 흉한 문자열을 반환합니다.
이에 대한 코드는 아래와 같습니다.
// Object.toString()의 구현코드
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
따라서, 자바 객체를 출력했을 때 나오는 결과물 com.tistory.com.ExampleObject@2f92e0f4 는 아래와 같이 설명이 가능합니다.
- com.tistory.jaimemin.ExampleObject - 클래스의 이름, 즉 com.tistory.jaimemin 패키지 내에 있는 ExampleObject 클래스입니다.
- @ - 문자열을 함께 결합합니다.
- 2f92e0f4 객체의 해시 코드입니다.
배열 클래스의 이름은 조금 다르게 생겼으며, JavaDocs 문서 내 Class.getName() 항목에서 잘 설명되어있습니다.
예를 들어 [Ljava.lang.String 이 출력되었다면,
- [ - 일차원 배열 ([[는 이차원 배열, [[[는 삼차원 배열, 등등)
- L - 배열에 클래스 또는 인터페이스가 포함되어 있다는 뜻
- java.lang.String - 배열 타입 유형
출력 결과를 커스터마이징하기
System.out.println(myObject)을 호출할 때 출력 결과가 바뀌길 원한다면 toString() 메서드를 오버라이딩해야 합니다.아래는 간단한 예시입니다.
public class Person {
private String name;
// 생성자 및 다른 함수 중략
@Override
public String toString() {
return name;
}
}
이제 Person 객체를 출력하면 com.tistory.jaimemin.Person@12345678이 출력되는 대신 name 필드가 출력될 것입니다.
주의할 점: ToString() 메서드는 객체를 문자열로 변환하는 여러 가지 방법 중 한 가지 방법일 뿐입니다. 일반적으로 toString() 메서드는 객체를 명확하고 간결하게 설명하면서 완벽하게 설명해줘야 합니다.
따라서, 보다 나은 예제는 아래와 같습니다.
@Override
public String toString() {
return getClass().getSimpleName() + "[name=" + name + "]";
}
위와 같은 예제를 적용하면 Person 객체를 출력했을 때 Person [name=jaimemin]과 같이 출력될 것이고 이는 디버깅/테스트에 정말 유용한 자료가 될 것입니다.
출력 자동생성
많은 IDE는 클래스의 필드를 기반으로 toString() 메서드를 자동 생성할 수 있도록 지원합니다. (보다 많은 내용은 Eclipse 혹은 Intellij 문서를 확인해주시기 바랍니다.)
몇몇 인기 있는 자바 라이브러리들도 이 기능을 제공하는데 아래에 몇 가지 예시를 들도록 하겠습니다.
- Apache Commons Lang의 ToStringBuilder
- Google Guava의 MoreObjects.ToStringHelper
- Lombok의 @ToString
배열에 속해있는 자바 객체들을 출력하는 방법
객체 배열이 있는 경우 Arrays.toString()을 호출하여 배열 내용을 간단히 표시할 수 있습니다.
Person 타입 배열을 예시로 들자면 아래와 같습니다.
public class Person {
private String name;
// 생성자 및 다른 함수 중략
@Override
public String toString() {
return name;
}
}
Person[] people = { new Person("Fred"), new Person("Mike") };
System.out.println(Arrays.toString(people));
// 출력 결과: [Fred, Mike]
참고: 위 예시는 Arrays 클래스의 정적 메서드인 toString()을 호출한 예시입니다. 이 메서드는 앞서 설명한 toString 메서드와 다를 메서드입니다.
다차원 배열일 경우 Arrays.deepToString() 메서드를 통해 동일한 종류의 출력을 얻을 수 있습니다.
Collections
대부분의 컬렉션은 모든 객체에 대해 .toString() 호출을 기반으로 한 예쁜 출력을 지원합니다. (여기서 말하는 예쁜 출력은 com.tistory.com.ExampleObject@2f92e0f4 와 같이 못생긴 출력이 아니라는 뜻입니다.)
public class Person {
private String name;
// 생성자 및 다른 함수 중략
@Override
public String toString() {
return name;
}
}
List<Person> people = new ArrayList<>();
people.add(new Person("Alice"));
people.add(new Person("Bob"));
System.out.println(people);
// 출력결과: [Alice, Bob]
따라서 위에서 설명한 대로 자바 객체에 toString() 메서드가 원하는 대로 출력하는지만 확인하면 됩니다.
[출처]stackoverflow.com/questions/29140402/how-do-i-print-my-java-object-without-getting-sometype2f92e0f4
'[DEV] 기록' 카테고리의 다른 글
Intellij IDEA(인텔리제이) 단축키 정리 (1) | 2021.03.02 |
---|---|
[Java] json을 Java Object로 변환하는 방법 (0) | 2021.02.27 |
[RestTemplate] "[circuit_breaking_exception][parent]" Data too large, data for "[<http_request>]" would be error (0) | 2021.02.21 |
[elastic search] document 10,000개 이상 검색 하는 방법 (1) | 2021.02.05 |
[git] CLI 명령어 정리 (0) | 2021.01.31 |