Факты
- toString предназначен для преобразования объекта в строку, но он не обязан обеспечить обратимое преобразование. Т.е. гарантировать, что по полученной строке можно восстановить объект. Пример: может распечатывать не все поля
- toString предназначен для людей, а не для машин. Он должен обеспечить удобное для человека строковое представление. Пример: "ColoredPoint[x=2,y=4,color=RED]". Пример: "Phone[(097)345-65-32]".
- неосторожный вызов toString для полей может привести к прямой или косвенной беcконечной рекурсии и StackOverflowException.
- "эталонная реализация toString" у java.awt.Point
String str = new Point(1,2).toString(); // str == "Point[x=1,y=2]"
Материалы
[Effective Java] стр 39: "Всегда переопределяйте метод toString"
Примеры
Замечания:
1) Строка "emp = " + emp вызвала String.valueOf(Object), который вызвал emp.toString(). Вопрос - а почему не вызвали напрямую emp.toString()?
2) У массивов toString() не переопределен, поэтому пользуемся утилитарным методом Arrays.toString(int[]). Вопрос: а что вывел бы ", childrenAges=" + childrenAges?
3) У List-ов toString() должен быть переопределен, поэтому вызываем напрямую ", childrenNames=" + childrenNames, что неявно вызывает String.valueOf(Object), который вызвал emp.toString().
4) Инициализацию childrenNames можно было бы сделать в одну строку
Лабораторные
oop.tostring.plain_address (обязательно)
Реализуйте метод toString у Address.
Address address = ...
System.out.println(address);
>> Address[country=.., city=.., street=.., houseNumber=..]
oop.tostring.plain_phone (обязательно)
Реализуйте метод toString у Phone. Он должен работать следующим образом:
System.out.println(new Phone(777, 1234567));
>> Phone[(777) 123-45-67]
oop.tostring.nested_employee (обязательно)
Реализуйте метод toString у NestedEmployee. Он должен работать следующим образом:
NestedEmployee emp = ...
System.out.println(emp);
>> NestedEmployee[age=.., name=.., address=Address[..], phone = Phone[...]]
Рекомендация: address и phone должны выводить себя сами.
oop.tostring.cyclic_ref_hand_cut
Реализуйте метод toString у CyclicEmployee, который "обрезает" вложенные поля, которые могут привести к рекурсии.
Замечание: getter/setter я пропустил - для краткости кода. Добавьте их сами.
oop.tostring.cyclic_ref_hand_expand (очень сложно)
Реализуйте метод toString у CyclikEmployee (из предыдущей лабораторной), который "разворачивает" вложенные поля, пока не встретит цикл.
Пример: проанализируйте, как реализован Arrays.deepToString(...)
oop.tostring.cyclic_ref_jakarta (сложно)
Сделайте задание oop.tostring.nested_employee с помощью библиотеки Jakarta Commons Lang 3.1. Используйте класс ToStringBuilder. Пример:
oop.tostring.cyclic_ref_jakarta_reflection (очень сложно)
Сделайте задание oop.tostring.cyclic_ref_hand_expand с помощью библиотеки Jakarta Commons Lang 3.1. Используйте класс ReflectionToStringBuilder.
- toString предназначен для преобразования объекта в строку, но он не обязан обеспечить обратимое преобразование. Т.е. гарантировать, что по полученной строке можно восстановить объект. Пример: может распечатывать не все поля
- toString предназначен для людей, а не для машин. Он должен обеспечить удобное для человека строковое представление. Пример: "ColoredPoint[x=2,y=4,color=RED]". Пример: "Phone[(097)345-65-32]".
- неосторожный вызов toString для полей может привести к прямой или косвенной беcконечной рекурсии и StackOverflowException.
- "эталонная реализация toString" у java.awt.Point
String str = new Point(1,2).toString(); // str == "Point[x=1,y=2]"
Материалы
[Effective Java] стр 39: "Всегда переопределяйте метод toString"
Примеры
import java.util.Arrays;
import java.util.List;
public class Employee {
public int age;
public String name;
public int[] childrenAges;
public List<String> childrenNames;
@Override
public String toString() {
return "Employee[" +
"age=" + age +
", name=" + name +
", childrenAges=" + Arrays.toString(childrenAges) +
", childrenNames=" + childrenNames + ']';
}
}
import java.util.ArrayList;
public class TestEmployeeToString {
public static void main(String[] args) {
Employee emp = new Employee();
emp.age = 35;
emp.name = "Mike";
emp.childrenAges = new int[]{2, 4, 7};
emp.childrenNames = new ArrayList<String>();
emp.childrenNames.add("Jimmy");
emp.childrenNames.add("Stella");
emp.childrenNames.add("Ann");
System.out.println("emp = " + emp);
}
}
>> emp = Employee[age=35, name=Mike, childrenAges=[2, 4, 7], childrenNames=[Jimmy, Stella, Ann]]Замечания:
1) Строка "emp = " + emp вызвала String.valueOf(Object), который вызвал emp.toString(). Вопрос - а почему не вызвали напрямую emp.toString()?
2) У массивов toString() не переопределен, поэтому пользуемся утилитарным методом Arrays.toString(int[]). Вопрос: а что вывел бы ", childrenAges=" + childrenAges?
3) У List-ов toString() должен быть переопределен, поэтому вызываем напрямую ", childrenNames=" + childrenNames, что неявно вызывает String.valueOf(Object), который вызвал emp.toString().
4) Инициализацию childrenNames можно было бы сделать в одну строку
import static java.util.Arrays.asList;
...
emp.childrenNames = asList("Jimmy", "Stella", "Ann");
Вопрос: List - это интерфейс, экземпляр какого именно класса вернул метод Arrays.asList(...)?Лабораторные
oop.tostring.plain_address (обязательно)
Реализуйте метод toString у Address.
public class Address {
private String country;
private String city;
private String street;
private int houseNumber;
}
Замечание: getter/setter я пропустил - для краткости кода. Добавьте их сами.Address address = ...
System.out.println(address);
>> Address[country=.., city=.., street=.., houseNumber=..]
oop.tostring.plain_phone (обязательно)
Реализуйте метод toString у Phone. Он должен работать следующим образом:
System.out.println(new Phone(777, 1234567));
>> Phone[(777) 123-45-67]
public class Phone {
private final int code;
private final int number;
public Phone(int code, int number) {
this.code = code;
this.number = number;
}
}
Замечание: getter-ы я пропустил - для краткости кода. Добавьте их сами.oop.tostring.nested_employee (обязательно)
Реализуйте метод toString у NestedEmployee. Он должен работать следующим образом:
NestedEmployee emp = ...
System.out.println(emp);
>> NestedEmployee[age=.., name=.., address=Address[..], phone = Phone[...]]
public class NestedEmployee {
private int age;
private String name;
private Address address;
private Phone phone;
}
Замечание: getter/setter я пропустил - для краткости кода. Добавьте их сами.Рекомендация: address и phone должны выводить себя сами.
oop.tostring.cyclic_ref_hand_cut
Реализуйте метод toString у CyclicEmployee, который "обрезает" вложенные поля, которые могут привести к рекурсии.
public class CyclicEmployee {
private int age;
private String name;
private CyclicEmployee boss;
private List<CyclicEmployee> subordinate;
}
>> Employee[age=30,name='Mike',boss=Employee[age=45,name='Ann'], subordinate=[Employee[age=25,name='Jimmy']]]Замечание: getter/setter я пропустил - для краткости кода. Добавьте их сами.
oop.tostring.cyclic_ref_hand_expand (очень сложно)
Реализуйте метод toString у CyclikEmployee (из предыдущей лабораторной), который "разворачивает" вложенные поля, пока не встретит цикл.
Пример: проанализируйте, как реализован Arrays.deepToString(...)
import java.util.Arrays;
class DeepToStringTest {
public static void main(String[] args) {
Object[] arr0 = new Object[] {new Object[0], 1, "Hi!", null};
Object[] arr1 = new Object[] {new Object[0], 1, "Hi!", null};
Object[] arr2 = new Object[] {new Object[0], 1, "Hi!", null};
arr0[3] = arr1;
arr1[3] = arr2;
arr2[3] = arr0;
System.out.println(Arrays.deepToString(arr0));
}
}
>> [[], 1, Hi!, [[], 1, Hi!, [[], 1, Hi!, [...]]]]oop.tostring.cyclic_ref_jakarta (сложно)
Сделайте задание oop.tostring.nested_employee с помощью библиотеки Jakarta Commons Lang 3.1. Используйте класс ToStringBuilder. Пример:
public class Person {
String name;
int age;
boolean smoker;
...
public String toString() {
return new ToStringBuilder(this).
append("name", name).
append("age", age).
append("smoker", smoker).
toString();
}
}
oop.tostring.cyclic_ref_jakarta_reflection (очень сложно)
Сделайте задание oop.tostring.cyclic_ref_hand_expand с помощью библиотеки Jakarta Commons Lang 3.1. Используйте класс ReflectionToStringBuilder.