Object ·
‹ Предыдущий Следующий ›
⏱ 5 минут чтения Обновлено: 2026-09-28

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

Вы создаёте объект Person, передаёте его в System.out.println(person) и вместо имени и возраста видите в консоли что-то вроде oop.Person@5e2a3193. Это не ошибка — так работает метод toString(), который класс унаследовал от Object и не переопределил.

Метод toString() в Java — это метод класса Object с сигнатурой public String toString(), который возвращает строковое представление объекта. Он есть у любого объекта, потому что все классы наследуются от Object. При создании нового класса метод toString() принято переопределять так, чтобы возвращаемая строка содержала имя класса и значения его основных полей.

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

Если класс не переопределяет метод, вызывается реализация из класса Object. Она устроена так:

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

То есть результат состоит из полного имени класса (вместе с пакетом), символа @ и хеш-кода объекта в шестнадцатеричном виде. Для класса Person из пакета oop это будет строка вида:

oop.Person@5e2a3193

Такая строка почти ничего не говорит о содержимом объекта, поэтому документация Java прямо рекомендует переопределять toString() во всех классах.

Важно

Число после @ — это не адрес объекта в памяти, а значение hashCode() в шестнадцатеричной записи. JVM может перемещать объекты при сборке мусора, а хеш-код при этом не меняется.

Переопределение метода toString()

Чтобы получить осмысленный вывод, в классе объявляют метод public String toString() с аннотацией @Override. Распространённый формат — ИмяКласса{поле=значение, ...}:

public class Person {
    private String fullName;
    private int age;
    private boolean retired;

    public Person(String fullName, int age, boolean retired) {
        this.fullName = fullName;
        this.age = age;
        this.retired = retired;
    }

    @Override
    public String toString() {
        return "Person{"
                + "fullName='" + fullName + '\''
                + ", age=" + age
                + ", retired=" + retired
                + '}';
    }
}

Чтобы увидеть результат, достаточно передать объект в System.out.println — метод toString() будет вызван автоматически:

public class PersonExample4 {
    public static void main(String[] args) {
        Person person = new Person("Петров Иван Иванович", 56, false);
        System.out.println(person);
    }
}

Результат выполнения программы:

Person{fullName='Петров Иван Иванович', age=56, retired=false}

Правила хорошей реализации toString():

  • указывайте имя класса и ключевые поля — строка должна помогать при отладке и чтении логов;
  • не обязательно включать все поля: пароли, токены, большие коллекции и ссылки «назад» на родительский объект лучше исключить;
  • метод не должен менять состояние объекта и выполнять тяжёлые вычисления;
  • всегда ставьте @Override — компилятор поймает опечатку в имени метода.

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

Когда toString() вызывается автоматически

Метод to string в Java редко вызывают вручную — чаще это делает сам язык или библиотека:

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

Разные способы получить строку по-разному обрабатывают null:

Выражение Объект не null Объект равен null
obj.toString() результат toString() NullPointerException
String.valueOf(obj) результат toString() строка "null"
"" + obj результат toString() строка "null"
Objects.toString(obj, "нет данных") результат toString() значение по умолчанию

Автогенерация toString(): IDE, Lombok, record

Писать toString() вручную для каждого класса не нужно:

  • 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]

Обратите внимание: у record формат с квадратными скобками, а не с фигурными, как у шаблона IntelliJ IDEA.

toString() для коллекций и массивов

Коллекции (ArrayList, HashMap и другие) toString() уже переопределяют и выводят элементы в квадратных или фигурных скобках. Но каждый элемент при этом печатается через свой собственный toString() — если он не переопределён в классе элемента, получится список вида [oop.Person@5e2a3193, oop.Person@6d06d69c].

Массивы, наоборот, toString() не переопределяют: System.out.println(numbers) выведет строку вида [I@1b6d3586. Чтобы напечатать элементы массива, используют метод Arrays.toString() — подробно он разобран в отдельном уроке Метод Arrays.toString() в Java.

Связь toString() с equals() и hashCode()

toString(), equals() и hashCode() — три метода класса Object, которые обычно переопределяют вместе. Но между ними есть разница: для equals() и hashCode() существует строгий контракт (равные объекты обязаны иметь равные хеш-коды), а для toString() — только рекомендация.

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

На чём чаще всего ошибаются

  • Бесконечная рекурсия. Если Department выводит список своих Employee, а каждый Employee выводит свой Department, вызов toString() закончится StackOverflowError. В одной из сторон связи выводите только идентификатор или имя.
  • Утечка чувствительных данных. toString() часто попадает в логи, поэтому пароли, номера карт и токены в него включать нельзя.
  • Опечатка в имени метода. Метод tostring() или toString(String s) — это новый метод, а не переопределение. Без @Override компилятор промолчит, и println() продолжит выводить Person@....
  • Разбор результата toString() в логике программы. Формат строки предназначен для людей и может поменяться. Для сравнения используйте equals(), для сериализации — JSON-библиотеки или отдельные методы.

Часто задаваемые вопросы

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

Нет. Это результат hashCode(), записанный в шестнадцатеричном виде. Хеш-код по умолчанию генерируется JVM и не совпадает с адресом объекта: сборщик мусора может переместить объект, а хеш-код останется прежним.

Обязательно ли переопределять toString()?

Нет, программа работает и без этого — в отличие от пары equals()/hashCode(), здесь нет контракта, нарушение которого ломает коллекции. Но документация Java рекомендует переопределять toString() во всех классах, потому что это сильно упрощает отладку и чтение логов.

Что возвращает toString() у enum?

По умолчанию — имя константы, то же значение, что и name(). toString() в enum можно переопределить, например, чтобы вернуть читаемое название, а метод name() объявлен final и всегда возвращает имя константы, как оно записано в коде.

Что будет, если переопределённый toString() вернёт null?

Код скомпилируется, а println() и конкатенация выведут строку null. Но это плохая практика: вызывающий код ожидает непустую строку, и obj.toString().length() упадёт с NullPointerException. Возвращайте хотя бы имя класса.

Видео объяснение

Предпочитаете видеоформат? Посмотрите этот урок с примерами и объяснениями.

Комментарии

hmma0723 Jun 15, 2017
I think the answer should be 'Both beans will use the same persistence context within the same transaction."

Зарегистрируйтесь или войдите, чтобы иметь возможность оставить комментарий.