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 .