Можно ли переопределять строку с помощью replace и substring в Java?
Что проверяют
Помните ли вы, что строка в Java неизменяема, и понимаете ли, что из этого следует. Вопрос звучит наивно, но за ним обычно идёт продолжение про пул строк, сравнение через == и склейку в цикле.
Как отвечать
Переопределить содержимое строки нельзя: String неизменяем, а replace и substring исходный объект не трогают, они возвращают новый. Изменится только переменная, и то если вы присвоите ей результат.
String s = "hello world";
s.replace("world", "java"); // результат выброшен, s прежняя
s = s.replace("world", "java"); // вот теперь s другаяПолезно уточнить детали, которые спрашивают следом. replace работает с обычным текстом, а replaceAll принимает регулярное выражение, поэтому точка в нём означает любой символ. Вариант replace с двумя символами при отсутствии нужного символа возвращает ту же самую ссылку, и новый объект не создаётся вовсе. substring берёт начало включительно и конец исключительно, а при выходе за границы бросает исключение.
Дальше скажите, зачем неизменяемость нужна: строку можно без опаски делить между потоками, кэшировать её хэш и хранить литералы в пуле. Если строку действительно надо собирать по кускам, для этого есть StringBuilder, а склейка плюсом в цикле создаёт объект на каждой итерации.
Где спотыкаются
Забывают присвоить результат. Вызов без присваивания спокойно компилируется, ничего не сообщает и просто не работает, а искать такое в большом методе неприятно.
Берут replaceAll там, где нужен обычный текст. Замена точки или скобки внезапно срабатывает как шаблон и портит строку, хотя ожидали буквальную подстановку.
Путают неизменяемость с безопасностью ссылки. Сама строка потокобезопасна, но поле, которое на неё указывает, переприсваивается из другого потока, и без final или синхронизации гонка никуда не девается.