Теперь, в Java, строки неизменяемы. Тогда почему объекту str может быть присвоено другое значение, например "Help!". Не противоречит ли это неизменяемости строк в Java? Кто-нибудь, пожалуйста, может объяснить мне точную концепцию неизменяемости?
Редактировать:
ОК. Теперь я понял, но только один последующий вопрос. Как насчет следующего кода:
Stringstr="Mississippi"; System.out.println(str); // prints Mississippi
str = str.replace("i", "!"); System.out.println(str); // prints M!ss!ss!pp!
Означает ли это, что два объекта создаются снова ("Mississippi" и "M!ss!ss!pp!"), а ссылка str указывает на другой объект после replace() метода?
Переведено автоматически
Ответ 1
str это не объект, это ссылка на объект. "Hello" и "Help!" это два разных String объекта. Таким образом, strуказывает на строку. Вы можете изменить то, на что оно указывает, но не то, на что оно указывает.
Возьмем, к примеру, этот код:
Strings1="Hello"; Strings2= s1; // s1 and s2 now point at the same string - "Hello"
Теперь нет ничего, что 1 мы могли бы сделать с s1, что повлияло бы на значение s2. Они ссылаются на один и тот же объект - строку "Hello" - но этот объект неизменяем и, следовательно, не может быть изменен.
Если мы сделаем что-то вроде этого:
s1 = "Help!"; System.out.println(s2); // still prints "Hello"
Здесь мы видим разницу между изменением объекта и изменением ссылки. s2 по-прежнему указывает на тот же объект, на который мы изначально указалиs1. Установка s1 в "Help!" значение изменяет только ссылку, в то время как String объект, на который она первоначально ссылалась, остается неизменным.
Если бы строки были изменяемыми, мы могли бы сделать что-то вроде этого:
Strings1="Hello"; Strings2= s1; s1.setCharAt(1, 'a'); // Fictional method that sets character at a given pos in string System.out.println(s2); // Prints "Hallo"
Отредактируйте, чтобы ответить на правку OP:
Если вы посмотрите на исходный код String.replace(char,символ) (также доступен в src.zip в вашем каталоге установки JDK ( профессиональный совет - заглядывать туда всякий раз, когда вам интересно, как что-то действительно работает) вы можете увидеть, что это делает следующее:
Если в текущей строке есть одно или несколько вхождений oldChar, создайте копию текущей строки, в которой все вхождения oldChar заменяются на newChar.
Если oldChar отсутствует в текущей строке, верните текущую строку.
Итак, да, "Mississippi".replace('i', '!') создает новый String объект. Опять же, выполняется следующее:
Strings1="Mississippi"; Strings2= s1; s1 = s1.replace('i', '!'); System.out.println(s1); // Prints "M!ss!ss!pp!" System.out.println(s2); // Prints "Mississippi" System.out.println(s1 == s2); // Prints "false" as s1 and s2 are two different objects
Ваше домашнее задание на данный момент - посмотреть, что сделает приведенный выше код, если вы измените s1 = s1.replace('i', '!'); на s1 = s1.replace('Q', '!'); :)
1 На самом деле, есть возможность изменять строки (и другие неизменяемые объекты). Это требует осмысления и очень, очень опасно, и его никогда не следует использовать, если вы действительно не заинтересованы в уничтожении программы.
Ответ 2
Объект, на который str ссылаются, может изменяться, но сами фактические String объекты изменяться не могут.
String Объекты, содержащие строку "Hello" и "Help!", не могут изменять свои значения, следовательно, они неизменяемы.
Неизменяемость String объектов не означает, что ссылки, указывающие на объект, не могут изменяться.
Один из способов предотвратить изменение str ссылки - объявить ее как final:
finalStringSTR="Hello";
Теперь попытка присвоить другое String значение STR вызовет ошибку компиляции.
Это создает новый "удаленный элемент управления" с именем "str" и присваивает ему значение new String() (или "").
например, в памяти это создает:
str --- > ""
str = "Hello";
Затем это изменяет удаленный элемент управления "str", но не изменяет исходную строку "".
например, в памяти это создает:
str -+ "" +-> "Hello"
str = "Help!";
Затем это изменяет удаленный элемент управления "str", но не изменяет исходную строку "" или объект, на который в данный момент указывает удаленный элемент управления.
например, в памяти это создает:
str -+ "" | "Hello" +-> "Help!"
Ответ 4
Давайте разберем это на несколько частей
Strings1="hello";
Этот оператор создает строку, содержащую hello, и занимает место в памяти, т.е. в пуле постоянных строк, и присваивает ее объекту-ссылке s1
Strings2= s1;
Этот оператор присваивает ту же строку hello новой ссылке s2
Поскольку строка неизменяема, виртуальная машина Java не позволит нам изменять строку s1 своим методом. Она создаст все новые объекты String в пуле следующим образом.
Вот почему Java решила, что String будет конечным классом В противном случае любой может модифицировать и изменять значение string . Надеюсь, это немного поможет.