Метод toString() в Java: переопределение и примеры - Вопросы

Всего: 5 вопросов

1. 

Что такое метод toString() в Java и что он возвращает по умолчанию?

toString() - метод класса Object с сигнатурой public String toString(), который возвращает строковое представление объекта. Он есть у любого объекта, так как все классы наследуются от Object.

Реализация по умолчанию:

return getClass().getName() + "@" + Integer.toHexString(hashCode());

То есть полное имя класса, символ @ и хеш-код в шестнадцатеричном виде, например oop.Person@5e2a3193. Поэтому toString() принято переопределять, чтобы строка содержала имя класса и значения основных полей.

2. 

Является ли число после @ в строке Person@5e2a3193 адресом объекта в памяти?

Нет. Это значение hashCode(), записанное в шестнадцатеричном виде (Integer.toHexString(hashCode())). JVM может перемещать объекты при сборке мусора, а хеш-код при этом не меняется.

Отсюда неочевидное следствие: если в классе переопределён hashCode(), но не toString(), два равных объекта напечатаются одинаково, например oop.Person@1f и oop.Person@1f.

3. 

В каких случаях метод toString() вызывается автоматически, без явного вызова в коде?

Неявно toString() вызывают:

  • System.out.println(obj) и System.out.print(obj);
  • конкатенация строк: "Клиент: " + person;
  • String.valueOf(obj), String.format("%s", obj), StringBuilder.append(obj);
  • логгеры (SLF4J, Log4j) при подстановке объекта в сообщение;
  • отладчик IDE при показе значения переменной.

Поэтому писать println(person.toString()) избыточно, а если person равен null, явный вызов бросит NullPointerException, тогда как println(person) просто выведет null.

4. 

Как сгенерировать toString() автоматически и какой toString() у record?

Способы автогенерации:

  • IntelliJ IDEA: Alt+Insert (на macOS Cmd+N) → toString(); шаблон по умолчанию даёт формат Person{fullName='...', age=56, retired=false};
  • Eclipse: Source → Generate toString()...;
  • Lombok: аннотация @ToString (или @Data), поля исключаются через @ToString.Exclude.

Записи (record, с Java 16) получают toString() автоматически вместе с equals() и hashCode(), но в формате с квадратными скобками:

public record Point(int x, int y) { }
System.out.println(new Point(1, 2)); // Point[x=1, y=2]
5. 

Какие ошибки чаще всего допускают при переопределении toString()?

  • Бесконечная рекурсия. Если Department выводит своих Employee, а каждый Employee - свой Department, вызов закончится StackOverflowError. В одной из сторон связи выводите только id или имя.
  • Утечка чувствительных данных. toString() попадает в логи, поэтому пароли, номера карт и токены в него не включают.
  • Опечатка в имени. tostring() или toString(String s) - новый метод, а не переопределение; без @Override компилятор промолчит.
  • Разбор результата toString() в логике. Формат предназначен для людей и может меняться; для сравнения используйте equals(), для сериализации - JSON-библиотеки.
  • Возврат null. Код скомпилируется, но вызывающий код ожидает строку, и obj.toString().length() упадёт с NullPointerException.
Страница 1 из 1