Как Java сравнивает значения String в конструкции switch, если String — ссылочный тип?
В switch по типу String Java сравнивает содержимое строк, а не ссылки, то есть использует семантику, эквивалентную equals. Поэтому разные объекты String с одинаковым текстом попадают в один case. При передаче null возникает NullPointerException.
Изначально switch в Java работал с целочисленными типами, перечислениями и некоторыми совместимыми с ними значениями. Поддержка String появилась в Java 7, чтобы заменить громоздкие цепочки сравнений строк и сделать ветвление по текстовым значениям более читаемым.
При этом в язык не добавляли сравнение ссылок через ==: для строкового switch потребовалась проверка именно логического равенства содержимого.
У переменных типа String могут быть разные ссылки на объекты с одинаковым текстом. Если бы switch сравнивал ссылки, результат зависел бы от интернирования строк, способа создания объекта и других деталей размещения строк в памяти.
Такое поведение сделало бы ветвление непредсказуемым: строковый литерал и строка, полученная из внешнего источника или созданная отдельно, могли бы вести себя по-разному. Дополнительный риск связан с null: у него нет содержимого, которое можно сравнить со значением case.
Для строкового switch Java определяет совпадение по значению строки. Концептуально проверка соответствует вызову equals для значения из case, а не сравнению ссылок через ==.
Здесь будет напечатано Запуск, хотя command и литерал "start" могут быть разными объектами. Компилятор обычно оптимизирует строковый switch, например группируя варианты по значениям hashCode, а затем выполняя проверку equals; конкретное машинное представление не следует считать частью исходной семантики Java.
Строки в case должны быть константными выражениями. Значения case не могут дублироваться по содержимому, даже если записаны как разные выражения, дающие одну и ту же строку.
Если выражение-селектор имеет значение null, выполнение завершается NullPointerException до выбора ветки. default обрабатывает отсутствие совпадения, но не заменяет отдельную проверку на null.
Сервис получает текстовую команду из HTTP-запроса и выбирает обработчик через switch. Вариант с == формально компилируется, но ошибочен: он сравнивает идентичность объектов, поэтому команда, созданная из тела запроса, может не совпасть с литералом.
Можно использовать цепочку if с equals, что явно показывает сравнение значений, но при большом числе команд такая конструкция становится длинной и менее удобной для сопровождения. Можно применить switch по String, сохранив компактность и корректную семантику сравнения.
Выбранный вариант — switch по строке с предварительной проверкой null или с нормализацией входа. Это сохраняет читаемость, избегает зависимости от интернирования и отдельно делает обработку некорректного входа явной.
null в качестве значения case?Нет. case для строкового switch должен быть константным строковым выражением, а null не является строковой константой. Кроме того, сам селектор со значением null приводит к NullPointerException, а не к переходу в default.
switch оператор ==?Нет, его логика не основана на идентичности ссылок. Совпадение определяется содержимым строк, эквивалентно проверке через equals; возможная внутренняя оптимизация через hashCode не меняет этого результата.
Нет. Объекты String неизменяемы. После вычисления значения селектора Java выбирает ветку на основании полученной строки, а операции, создающие изменённый текст, формируют новый объект и не меняют исходную строку.