Перейти к основному содержимому

Java-метод toString()

· 5 мин. чтения

1. Обзор

Каждый класс в Java прямо или косвенно является потомком класса Object . А поскольку класс Object содержит метод toString() , мы можем вызвать toString() для любого экземпляра и получить его строковое представление.

В этом руководстве мы рассмотрим поведение toString() по умолчанию и узнаем, как изменить его поведение.

2. Поведение по умолчанию

Всякий раз, когда мы печатаем ссылку на объект, он внутри вызывает метод toString() . Итак, если мы не определяем метод toString() в нашем классе, вызывается Object# toString() .

Метод объекта toString() довольно общий:

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

Чтобы увидеть, как это работает, давайте создадим объект Customer , который мы будем использовать в нашем руководстве:

public class Customer {
private String firstName;
private String lastName;
// standard getters and setters. No toString() implementation
}

Теперь, если мы попытаемся напечатать наш клиентский объект C , будет вызван Object # toString() , и вывод будет похож на: ``

com.foreach.tostring.Customer@6d06d69c

3. Переопределение поведения по умолчанию

Глядя на приведенный выше вывод, мы видим, что он не дает нам много информации о содержимом нашего объекта Customer . Как правило, нас интересует не хеш-код объекта, а содержимое атрибутов нашего объекта.

Переопределяя поведение метода toString() по умолчанию , мы можем сделать вывод вызова метода более осмысленным.

Теперь давайте рассмотрим несколько различных сценариев использования объектов, чтобы увидеть, как мы можем переопределить это поведение по умолчанию.

4. Примитивные типы и строки

Наш объект Customer имеет как строковые , так и примитивные атрибуты. Нам нужно переопределить метод toString() , чтобы получить более осмысленный вывод:

public class CustomerPrimitiveToString extends Customer {
private long balance;

@Override
public String toString() {
return "Customer [balance=" + balance + ", getFirstName()=" + getFirstName()
+ ", getLastName()=" + getLastName() + "]";
}
}

Давайте посмотрим, что мы получим, когда вызовем toString() :

@Test
public void givenPrimitive_whenToString_thenCustomerDetails() {
CustomerPrimitiveToString customer = new CustomerPrimitiveToString();
customer.setFirstName("Rajesh");
customer.setLastName("Bhojwani");
customer.setBalance(110);
assertEquals("Customer [balance=110, getFirstName()=Rajesh, getLastName()=Bhojwani]",
customer.toString());
}

5. Сложные объекты Java

Давайте теперь рассмотрим сценарий, в котором наш объект Customer также содержит атрибут заказа , который имеет тип Order. Наш класс Order имеет поля типа String и примитивного типа.

Итак, давайте снова переопределим toString() :

public class CustomerComplexObjectToString extends Customer {
private Order order;
//standard setters and getters

@Override
public String toString() {
return "Customer [order=" + order + ", getFirstName()=" + getFirstName()
+ ", getLastName()=" + getLastName() + "]";
}
}

Поскольку заказ является сложным объектом , если мы просто напечатаем наш объект Customer , не переопределяя метод toString() в нашем классе Order , он будет печатать заказы как Order@ <hashcode>.

Чтобы исправить это, давайте также переопределим toString() в Order :

public class Order {

private String orderId;
private String desc;
private long value;
private String status;

@Override
public String toString() {
return "Order [orderId=" + orderId + ", desc=" + desc + ", value=" + value + "]";
}
}

Теперь давайте посмотрим, что происходит, когда мы вызываем метод toString() для нашего объекта Customer , содержащего атрибут заказа :

@Test
public void givenComplex_whenToString_thenCustomerDetails() {
CustomerComplexObjectToString customer = new CustomerComplexObjectToString();
// .. set up customer as before
Order order = new Order();
order.setOrderId("A1111");
order.setDesc("Game");
order.setStatus("In-Shiping");
customer.setOrders(order);

assertEquals("Customer [order=Order [orderId=A1111, desc=Game, value=0], " +
"getFirstName()=Rajesh, getLastName()=Bhojwani]", customer.toString());
}

6. Массив объектов

Далее давайте изменим наш Customer , чтобы он имел массив Order s . Если мы просто напечатаем наш объект Customer без специальной обработки нашего объекта заказов , он напечатает заказы как Order;@<hashcode> .

Чтобы исправить это, давайте используем Arrays.toString() для поля заказов :

public class CustomerArrayToString  extends Customer {
private Order[] orders;

@Override
public String toString() {
return "Customer [orders=" + Arrays.toString(orders)
+ ", getFirstName()=" + getFirstName()
+ ", getLastName()=" + getLastName() + "]";
}
}

Давайте посмотрим на результаты вызова вышеуказанного метода toString() :

@Test
public void givenArray_whenToString_thenCustomerDetails() {
CustomerArrayToString customer = new CustomerArrayToString();
// .. set up customer as before
// .. set up order as before
customer.setOrders(new Order[] { order });

assertEquals("Customer [orders=[Order [orderId=A1111, desc=Game, value=0]], " +
"getFirstName()=Rajesh, getLastName()=Bhojwani]", customer.toString());
}

7. Обертки, коллекции и StringBuffers

Когда объект полностью состоит из оберток , коллекций или StringBuffer s , не требуется специальной реализации toString() , потому что эти объекты уже переопределяют метод toString() значимыми представлениями:

public class CustomerWrapperCollectionToString extends Customer {
private Integer score; // Wrapper class object
private List<String> orders; // Collection object
private StringBuffer fullname; // StringBuffer object

@Override
public String toString() {
return "Customer [score=" + score + ", orders=" + orders + ", fullname=" + fullname
+ ", getFirstName()=" + getFirstName() + ", getLastName()=" + getLastName() + "]";
}
}

Давайте снова посмотрим на результаты вызова toString() :

@Test
public void givenWrapperCollectionStrBuffer_whenToString_thenCustomerDetails() {
CustomerWrapperCollectionToString customer = new CustomerWrapperCollectionToString();
// .. set up customer as before
// .. set up orders as before
customer.setOrders(new Order[] { order });

StringBuffer fullname = new StringBuffer();
fullname.append(customer.getLastName()+ ", " + customer.getFirstName());

assertEquals("Customer [score=8, orders=[Book, Pen], fullname=Bhojwani, Rajesh, getFirstName()=Rajesh, "
+ "getLastName()=Bhojwani]", customer.toString());
}

8. Заключение

В этой статье мы рассмотрели создание собственных реализаций метода toString() .

Весь исходный код этой статьи доступен на GitHub .