Сравнение строк в Java: интернирование, синхронизация и результаты операторов ==

Вывод — true, false, false. В объяснении условия есть ошибка: String.valueOf(Object) не обязан создавать строку; здесь он вызывает toString у уже созданного String и возвращает тот же объект.

Короткий ответ

Что ответить на собеседовании

Вывод — true, false, false. В объяснении условия есть ошибка: String.valueOf(Object) не обязан создавать строку; здесь он вызывает toString у уже созданного String и возвращает тот же объект.

Подробный разбор

Ответ с пояснениями

Условие

Разберите, какой вывод получит программа и почему. Объясните различия между переменными a, a1, a2 и a3, где происходит интернирование строк, и можно ли использовать строки в качестве монитора для синхронизации. Какие потенциальные проблемы могут возникнуть при таком подходе?

public class StringQuiz {
    public static void main(String[] args) {
        String a = "aaaa";
        String a1 = "aaaa";
        String a2 = new String("aaaa");
        String a3 = String.valueOf(new String("aaaa"));

        System.out.println(a == a1); // ?
        System.out.println(a == a2); // ?
        System.out.println(a == a3); // ?
    }
}

Что нужно объяснить:

  1. Почему a == a1 возвращает true (обе ссылки указывают на одну интернированную строку).
  2. Почему a == a2 возвращает false (объект создан оператором new, находится в heap, не интернирован).
  3. Почему a == a3 тоже false – String.valueOf создаёт новую строку, а не использует уже интернированную константу.
  4. Где именно в коде происходит интернирование (при загрузке литерала "aaaa").
  5. Возможна ли синхронизация на объекте String (synchronized (a) { … }). Обсудите, что это технически допустимо, но может привести к непредсказуемым конфликтам, так как одинаковые литералы в разных частях программы могут ссылаться на один и тот же объект, тем самым создавая скрытую блокировку между независимыми участками кода.
  6. Какие альтернативы безопаснее (использовать отдельный объект‑мьютекс).

Ответ

Вывод — true, false, false. В объяснении условия есть ошибка: String.valueOf(Object) не обязан создавать строку; здесь он вызывает toString у уже созданного String и возвращает тот же объект.

A и a1 получают интернированный литерал. A2 создаётся через new. Для a3 выражение new String("aaaa") тоже создаёт отдельный объект, а String.toString возвращает себя; автоматического intern у valueOf нет. Синхронизация на String технически возможна, но литералы могут разделяться независимым кодом, создавая скрытую общую блокировку. Предпочтителен private final Object lock = new Object(), который не публикуется наружу.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее