«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
}

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

[email protected]

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

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

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

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

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

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


public class CustomerPrimitiveToString extends Customer {
    private long balance;

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

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

@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());
}

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

Так как заказ является сложным объектом, если мы просто напечатаем наш объект Customer, не переопределяя метод toString() в нашем классе Order, он будет печатать заказы как [электронная почта защищена]\u003cхэш-код\u003e.

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

public class CustomerComplexObjectToString extends Customer {
    private Order order;
    //standard setters and getters
    
    @Override
    public String toString() {
        return "Customer [order=" + order + ", getFirstName()=" + getFirstName()
          + ", getLastName()=" + getLastName() + "]";
    }      
}

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

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


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 + "]";
    }
}

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

@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());
}

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

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

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

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

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

Когда объект полностью состоит из оболочек, коллекций или StringBuffers, не требуется специальной реализации toString(), поскольку эти объекты уже переопределяют метод 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());
}

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

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

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());
}

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

«

All of the source code for this article is available over on GitHub.