JAVA

toString을 재정의하기 (+ python)

윤듀2 2024. 1. 21. 15:42

개요

테스트코드에서 object의 필드값들이 다양한 type들로 이루어져 있었기 때문에 편한 게 String으로 변환하여 같은지를 테스트를 해보려고 했었다. 

하지만 toString을 재정의해주지 않으면 최상위 클래스인 Object의 toString이 호출되어서 클래스풀네임@해시코드로 출력되기 때문에 원하는 행위를 하기 위해서는 반드시 재정의 해줘야한다.

 

toString 용도

주로 디버깅하거나 로깅을 할 때 사용된다. toString()을 사용하면 객체를 문자열로 랜더링을 하여 객체의 내부 상태를 문자열로 반환할 수 있다.

문제

코드

public class Person {
    private final String name;
    private final String age;

    public Person(String name, String age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public String getAge() {
        return age;
    }
}
public class Main {
    public static void main(String[] args) {
        Person person1 = new Person("Jay", "40");
        Person person2 = new Person("Jay", "40");

        String person1ToString = person1.toString();
        String person2ToString = person2.toString();

        System.out.println(person1ToString);
        System.out.println(person2ToString);

    }
}

 

person object를 toString을 하게 되면 object의 toString이 호출되어 클래스풀네임@해시코드로 출력이 된다.

 

결과

org.example.Person@7ad041f3
org.example.Person@251a69d7

 

 

 해결

1. toString() Override 하기

intellij에서 cmd+N 누르면 toString을 자동으로 override 해준다.

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }

 

test 코드

class PersonTest {

    @Test
    public void 객체를_toString_했을_때_상태_확인하기() throws Exception {

        // Given
        Person person = new Person("Jay", "40");

        // When
        String result = person.toString();

        // Then
        String expected = "Person{name='Jay', age='40'}";
        assertEquals(expected, result);

    }
  }

 

만약 클래스 타입을 포함한 Object인 경우에는 어떻게 toString을 해야 할까?

 Person에 Address 타입을 가지고 있다고 해보자.

그러면 Address 클래스 안에서 toString을 재정의 해줘야 한다.

 

Address code

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

}

 

test code

lombok 써서 빌더패턴을 사용하였다.

class PersonTest {

    @Test
    public void 객체를_포함한_객체를_toString_했을_때_상태_확인하기() throws Exception {

        //Given
       Person person = Person.builder()
               .name("Jay")
               .age("30")
               .address(new Address("New York","New York"))
               .build();

        //When
        String result = person.toString();

        //Then
        String expected = "Person{name='Jay', age='30', address=Address{city='New York', state='New York'}}";
        
        assertEquals(expected, result);
    }



}

 

 

2. Lombok @ToString

lombok toString을 쓰게 되면 모든 필드를 포함하여 toString이 재정의가 된다.  편하게 사용할 수 있지만 문제점이 있다.

만약 필드하나가 다른 클래스의 객체를 참조하고 있다면, 해당 참조된 객체의 toString() 메서드가 호출된다.

 

 

서로 참조가 된 경우에 두 클래스 간에 toString() 메서드가 서로를 호출하면서 무한 루프에 빠지게 된다. 

그래서 직접 재정의해서 사용하는 것을 더 선호한다.

 

 

python에서는 toString을 어떻게 사용할까?

python에서는 java처럼 toString() 메서드는 없지만 같은 기능을 가진 여러 가지 메서드를 제공한다.그중에서 몇 가지만 이 포스팅에 넣고 더 알고 싶으면 참고한 문서링크를 넣었으니 확인해 보면 좋을 거 같다.

 

1.  str()

객체를 문자열로 변환하는 내장함수이다. 다양한 타입의 인수를 받아 문자열로 변환한다.

# List
a = [1, 2, 3, 4]
b = str(a)

# integer
num = 1 + 5
numToString = str(num)

#String
num2 = "1+5"
num2ToString = str(num2)

print("List:", b)
print("Number:", numToString)
print("String:", num2ToString)

 

 

output

List: [1, 2, 3, 4]
Number: 6
String: 1+5

 

 

참고

https://favtutor.com/blogs/tostring-convert-string-python