toString() 메서드 올바르게 사용하기

wnajsldkf·2022년 6월 24일
3

Java

목록 보기
3/19
post-thumbnail

첫번째 로또 미션을 수행하면서 결과값을 출력할 때 toString()을 재정의하여 구현하였다.

우리가 toString()을 사용한 이유는 1) getter의 사용을 지양하고, 2) 결과값을 쉽게 출력할 수 있기 때문이다.

하지만 이 경우 출력의 요구사항이 바뀐다면, Domain이 View에 의존하기 때문에(즉, View가 바뀌면 Domain도 바뀐다.) 적절하지 않다는 피드백을 받았다.
(Update 2022.06.27)
위 피드백에 대한 추가 피드백으로 Domain의 toString()을 구현했을 뿐, View에 의존한다고 보기 어렵다고 한다. View에서는 Domain의 toString()을 받아서 Domain을 변경하지 않고도 출력 형식을 자유롭게 변경할 수 있기 때문이다.

피드백을 반영하며 toString()에 대해 알아보니 우리는 용도에 맞게 toString()을 사용하고 있지 않았고, 공부가 필요함을 알았다.

toString() 메서드란?

toString() 메서드는 자바 클래스의 최고 조상 클래스인 Object 클래스의 메서드이다. 인스턴스에 대한 정보를 문자열로 반환하기 때문에, 인스턴스의 정보를 출력하는데 사용된다.

public class Test {
    public static void main(String[] args) {
        Car car01 = new Car();
        Car car02 = new Car();

        System.out.println(car01.toString());   // Car@3f0ee7cb
        System.out.println(car02.toString());   // Car@75bd9247
    }
}

반환되는 문자열은 클래스 이름과 함께 구분자 ‘@’와 16진수 해시 코드(hash code)가 추가된다. 16진수 해시 코드 값은 인스턴스의 주소를 가리킨다.

public class Test {
	public static void main(String[] args) {
		String str = "test";
		File file = new File("D//test");
		Integer integer = 1;
		Number number = 2;		

		System.out.println(str.toString());     // test
		System.out.println(file.toString());    // D/test
		System.out.println(integer.toString()); // 1
		System.out.println(number.toString());  // 2
	}
}

String, File, Integer, Number 클래스 객체의 메서드는 자신이 가진 값을 그대로 반환하는 것을 알 수 있다. 이 클래스는 내부에서 자신이 가진 값을 그대로 반환하는 메서드인 “toString”을 재정의(Override)해서 사용하기 때문이다.

박스 부분을 보면 toString 메서드를 재정의했음을 알 수 있다.

재정의한 String 클래스를 보면 가진 값을 그대로 반환하는 toString() 메서드가 작성된 것을 확인할 수 있다.

String.java

public String toString() {
	return this;
}

toString() 메서드를 재정의하기

재정의(Override)란 부모 클래스에서 정의된 메서드를 자식 클래스에서 다시 작성하는 것을 말한다.

앞에서 주소 값으로 나온 Car 클래스를 재정의하여 등록한 이름을 출력해보겠다.

(Mac에서 IntelliJ IDE를 사용한다면 cmd+n으로 toString()을 생성할 수 있다.)

오버라이딩한 함수가 생기는데 이 함수를 재정의하여 사용하면 된다.

@Override
public String toString() {
        return "Car{" +
                "이름은 " + car +
                '}';
    }

Car 객체를 사용하여 toString 메서드를 사용하면 재정의한 메서드가 제대로 호출되었음을 확인할 수 있다.

public class Test {
    public static void main(String[] args) {
        Car car = new Car();
				car.setCar("july's car");

				System.out.println(car.toString());    // Car{이름은 july's car}
		}
}

toString() 메서드는 자동으로 호출된다.

public static void main(String[] args) {
    Car car = new Car();
    car.setCar("july's car");

    String str = "This is my car";

    System.out.println(car);   // Car{이름은 july's car}
    System.out.println(str);   // This is my car
}

car는 Car의 객체, str은 String의 객체이지만 독단적으로 사용된다. 이는 toString이 자동으로 호출되기 때문이다.

그럼, toString()은 언제 사용하는게 좋을까?

toString() 메서드는 인스턴스에 대한 정보를 쉽게 출력할 수 있고 메서드를 재정의하여 원하는 형태로 출력할 수 있다는 장점이 있다.

이러한 장점 때문에 toString()을 디버깅 용도로 사용할지, 실제 기능 구현에 사용할지에 대한 고민이 종종 발생한다. 하지만 toString(): for debugging or for humans?을 참고하면 toString()은 디버깅에 적합하다는 의견이 다수인 것을 확인할 수 있다. 실제로 Object에서 toString() 메서드를 사용하면 주소값이 나오는데 이 값은 제품에는 사용되지 않기 때문이다. 위에서 이야기했지만 String, File 에서 사용한 toString()은 가진 값을 그대로 반환하는 메서드를 재정의했기 때문에 값을 그대로 확인할 수 있는 것이다.

Effective 자바의 아이템 12 “toString을 항상 재정의하라”에서도 toString을 재정의한 클래스는 사용하기도 쉽고, 디버깅도 쉽기 때문에 명확하고 유용한 정보를 읽기 좋은 형태로 반환해야한다고 이야기한다.

피드백을 반영하여 사용자에게 보여지는 코드는 toString()이 아닌 별도의 메서드를 작성하여 구현했다. toString()에 대해 알아보니 디버깅을 위해 사용하는 것이 적합함을 알았다. 또한 사용할 때는 재정의하여 디버깅에 효과적이도록 값을 반환해야한다.

Reference

profile
https://mywnajsldkf.tistory.com -> 이사 중

0개의 댓글