Рассмотрим следующий пример.
String str = new String();
str = "Hello";
System.out.println(str); //Prints Hello
str = "Help!";
System.out.println(str); //Prints Help!
Теперь в Java объекты String неизменны. Тогда как же объекту str
может быть присвоено значение «Помощь!». Разве это не противоречит неизменности строк в Java? Кто-нибудь может объяснить мне точную концепцию неизменности?
Редактировать:
Хорошо. Теперь я понимаю, но только один дополнительный вопрос. Как насчет следующего кода:
String str = "Mississippi";
System.out.println(str); // prints Mississippi
str = str.replace("i", "!");
System.out.println(str); // prints M!ss!ss!pp!
Означает ли это, что два объекта создаются снова («Миссисипи» и «M! Ss! Ss! Pp!»), И ссылка str
указывает на другой объект после replace()
метода?
java
string
immutability
Light_handle
источник
источник
Ответы:
str
это не объект, это ссылка на объект."Hello"
и"Help!"
два разныхString
объекта. Таким образом,str
указывает на строку. Вы можете изменить то, на что оно указывает , но не то, на что оно указывает .Возьмите этот код, например:
Теперь нет ничего 1 мы могли бы сделать , чтобы ,
s1
что бы повлиять на стоимостьs2
. Они ссылаются на один и тот же объект - строку"Hello"
- но этот объект является неизменным и, следовательно, не может быть изменен.Если мы сделаем что-то вроде этого:
Здесь мы видим разницу между изменением объекта и изменением ссылки.
s2
по-прежнему указывает на тот же объект, на который мы изначальноs1
указали. Установкаs1
для"Help!"
изменяет только ссылку , в то время какString
объект он первоначально означавшего остается неизменной.Если бы строки были изменяемыми, мы могли бы сделать что-то вроде этого:
Изменить, чтобы ответить на редактирование OP:
Если вы посмотрите на исходный код для String.replace (char, char) (также доступный в src.zip в вашем установочном каталоге JDK - совет для профессионалов - смотреть туда, когда вам интересно, как что-то действительно работает), вы можете увидеть, что это следующее:
oldChar
в текущей строке есть одно или несколько вхождений , сделайте копию текущей строки, на которуюoldChar
заменены все вхожденияnewChar
.oldChar
в текущей строке нет, вернуть текущую строку.Так что да,
"Mississippi".replace('i', '!')
создает новыйString
объект. Опять же, верно следующее:Ваша домашняя работа на данный момент состоит в том, чтобы увидеть, что делает приведенный выше код, если вы измените
s1 = s1.replace('i', '!');
наs1 = s1.replace('Q', '!');
:)1 На самом деле, это является можно мутировать строки (и другие неизменные объекты). Это требует размышлений и очень, очень опасно и никогда не должно использоваться, если вы действительно не заинтересованы в уничтожении программы.
источник
Объект, который
str
ссылается, может измениться, ноString
сами объекты не могут.String
Объекты , содержащая строку"Hello"
и"Help!"
не может изменить их, следовательно , они неизменны.Неизменность
String
объектов не означает, что ссылки, указывающие на объект, не могут измениться.Один из способов предотвратить изменение
str
ссылки - объявить ее следующим образомfinal
:Теперь, пытаясь назначить другой ,
String
чтобыSTR
вызовет ошибку компиляции.источник
str
это не «объект», это ссылка на объект. Если выString str = "Hello";
последовалиString anotherReference = str;
вам не 2 объекта String, у вас есть один объект (буквальная «Hello») и 2 ссылки на него (str
иanotherReference
).Light_handle Я рекомендую вам прочитать « Размер чашки» - рассказ о переменных и Проходном значении, пожалуйста (Продолжение размера чашки) . Это очень поможет при чтении постов выше.
Читали ли вы их? Да. Хорошо.
Это создает новый «пульт дистанционного управления» под названием «
str
» и устанавливает его в значениеnew String()
(или""
).например, в памяти это создает:
Это затем изменяет пульт дистанционного управления "
str
", но не изменяет исходную строку""
.например, в памяти это создает:
Это затем изменяет пульт дистанционного управления "
str
", но не изменяет исходную строку""
или объект, на который в данный момент указывает пульт дистанционного управления.например, в памяти это создает:
источник
Давайте разбить его на несколько частей
Этот оператор создает строку, содержащую привет и занимает место в памяти, т. Е. В пуле константных строк, и назначает ее ссылочному объекту s1.
Этот оператор присваивает ту же строку привет новой ссылке s2
Обе ссылки указывают на одну и ту же строку, поэтому выведите одно и то же значение следующим образом.
Хотя String является неизменным , присваивание может быть возможным, поэтому s1 теперь будет ссылаться на новый стек значений .
Но что касается объекта s2, который указывает на привет, все будет так, как есть.
Поскольку String является неизменным, виртуальная машина Java не позволяет нам изменять строку s1 ее методом. Он создаст все новые объекты String в пуле следующим образом.
Обратите внимание, что если строка будет изменяемой, то результат будет
Теперь вы можете быть удивлены, почему String имеет такие методы, как concat () для изменения. Следующий фрагмент очистит ваше замешательство.
Здесь мы присваиваем измененное значение строки назад ссылке s1 .
Вот почему Java решила, что String является конечным классом. В противном случае любой может изменить и изменить значение строки. Надеюсь, это поможет немного.
источник
Строковый объект, на который впервые ссылался объект,
str
не был изменен, все, что вы сделали, это сделали,str
ссылались на новый строковый объект.источник
Строка не изменится, ссылка на нее изменится. Вы путаете неизменность с понятием
final
полей. Если поле объявлено какfinal
, после того, как оно было назначено, оно не может быть переназначено.источник
Что касается замены части вашего вопроса, попробуйте это:
источник
Хотя Java пытается игнорировать это,
str
это всего лишь указатель. Это означает, что когда вы впервые пишетеstr = "Hello";
, вы создаете объект, на которыйstr
указывает. Когда вы переназначаетеstr
записьstr = "Help!";
, создается новый объект, и старый"Hello"
объект получает мусор всякий раз, когда Java чувствует, что это так.источник
Неизменность подразумевает, что значение экземпляра объекта не может измениться, вы никогда не сможете превратить «Hello» в «Help!».
Переменная str является ссылкой на объект, когда вы присваиваете str новое значение, вы не изменяете значение объекта, на который она ссылается, вы ссылаетесь на другой объект.
источник
Строковый класс является неизменным, и вы не можете изменить значение неизменяемого объекта. Но в случае String, если вы измените значение строки, это создаст новую строку в пуле строк, а затем ваша строковая ссылка на это значение, а не старое. таким образом, строка неизменна. Давайте возьмем ваш пример,
он создаст одну строку "Миссисипи" и добавит ее в пул строк, поэтому теперь str указывает на Миссисипи.
Но после вышеуказанной операции будет создана еще одна строка "M! Ss! Ss! Pp!" и он будет добавлен в пул строк. и теперь str указывает на M! ss! ss! pp !, а не на Миссисипи.
таким образом, когда вы измените значение строкового объекта, он создаст еще один объект и добавит его в пул строк.
Давайте еще один пример
эта строка из трех выше добавит три объекта строки в пул строк.
1) Привет
2) Мир
3) ПриветWorld
источник
Использование:
Если вы видите здесь, я использую
concat
метод для изменения исходной строки, то есть «New String» со строкой «Added String», но все же я получил вывод как и предыдущий, следовательно, это доказывает, что вы не можете изменить ссылку на объект класса String, но если вы сделаете это с помощью класса StringBuilder, это сработает. Это перечислено ниже.источник
Как сказал Линус Толвардс:
Взгляните на это:
Выход
Итак, помните две вещи:
источник
Для тех, кто интересуется, как нарушить неизменность String в Java ...
Код
Вывод
источник
Строка является непреложным . Это означает, что мы можем только изменить ссылку .
источник
В Java к объектам обычно обращаются по ссылкам. В вашем фрагменте кода str есть ссылка, которая сначала присваивается «Hello» (автоматически созданный объект или извлекается из постоянного пула ), а затем вы назначаете другой объект «Help!» к той же ссылке. Следует отметить, что ссылка такая же и изменена, но объекты разные. Еще одна вещь в вашем коде вы получили доступ к трем объектам,
Вызов new String () создает новый объект, даже если он существует в пуле строк, поэтому обычно его не следует использовать. Чтобы поместить строку, созданную из new String () в пул строк, вы можете попробовать
intern()
метод.Надеюсь, это поможет.
источник
Неизменность Я могу сказать, что вы не можете изменить саму строку. Предположим, у вас есть строка x, значение которой равно «abc». Теперь вы не можете изменить строку, то есть вы не можете изменить любой символ (ы) в «abc».
Если вам нужно изменить какие-либо символы в строке, вы можете использовать массив символов и изменить его или использовать StringBuilder.
Вывод:
источник
Или вы можете попробовать:
Это покажет, как изменяется хэш-код.
источник
Строка неизменна означает, что вы не можете изменить сам объект, но вы можете изменить ссылку на объект. Когда вы вызываете a = "ty", вы фактически изменяете ссылку a на новый объект, созданный строковым литералом "ty". Изменение объекта означает использование его методов для изменения одного из его полей (или поля являются общедоступными и не являются окончательными, чтобы их можно было обновлять извне, не обращаясь к ним через методы), например:
Находясь в неизменяемом классе (объявленном как final, чтобы предотвратить изменение с помощью наследования) (его методы не могут изменять его поля, а также поля всегда являются закрытыми и рекомендуются быть окончательными), например, String, вы не можете изменить текущую строку, но вы может вернуть новую строку, т.е.
источник
Здесь неизменность означает, что экземпляр может указывать на другую ссылку, но исходное содержимое строки не будет изменено при исходной ссылке. Позвольте мне объяснить первым примером, данным вами. Первая строка указывает на «Привет», все в порядке до этого. Второй раз это указывает на «Помощь!». Здесь ул начал указывать на «Помощь!» и ссылка на строку "Hello" потеряна, и мы не можем получить это обратно.
Фактически, когда str попытается изменить существующее содержимое, тогда будет сгенерирована другая новая строка, и str начнет указывать на эту ссылку. Таким образом, мы видим, что строка в исходной ссылке не изменяется, но это безопасно при ее ссылке, и экземпляр объекта начинает указывать на другую ссылку, поэтому неизменность сохраняется.
источник
Супер опоздал к ответу, но хотел выложить краткое сообщение от автора класса String на Java
Из этой документации можно сделать вывод, что все, что изменяет строку, возвращает другой объект (который может быть новым или интернированным и старым). Не очень тонкий намек на это следует из сигнатуры функции. Подумайте об этом: «Почему они заставляют функцию возвращать объект вместо статуса?».
Также еще один источник, который делает это поведение явным (из документации замены функции)
Источник: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replace(char,%20char)
Источник: JavaDoc String.
источник
Строка Object - методы сами по себе сделаны «неизменяемыми». Это действие не вызывает изменений: "letters.replace (" bbb "," aaa ");"
Но назначение данных приводит к изменениям содержимого строк:
// Хеш-код строки Object не изменяется.
источник
Если
HELLO
ваша строка, то вы не можете изменитьHELLO
наHILLO
. Это свойство называется свойством неизменности.Вы можете иметь несколько строковых переменных-указателей для указания HELLO String.
Но если HELLO - char Array, тогда вы можете изменить HELLO на HILLO. Например,
Языки программирования имеют неизменные переменные данных, чтобы их можно было использовать в качестве ключей в ключе и паре значений.
источник
Я бы объяснил это простым примером
на массиве символов мы можем выполнять такие операции, как печать только трех последних букв, используя итерацию массива; но в строке мы должны создать новый объект String и скопировать требуемую подстроку, и ее адрес будет в новом объекте string.
например
поэтому у s2 будет "hel";
источник
Строка в Java в Immutable и Final означает, что ее нельзя изменить или изменить:
Случай 1:
Случай 2:
источник
Поскольку String является неизменным, изменения не произойдут, если вы не будете присваивать возвращаемое значение функции для string.so. В своем вопросе присвойте возвращаемое значение функции swap s.
s = swap (s, n1, n2), тогда значение строки s изменится.
Я также получал неизменное значение, когда писал программу, чтобы получить строку перестановок (хотя она не дает всех перестановок, но это, например, для ответа на ваш вопрос)
Вот пример.
но я не получал переставленные значения строки из приведенного выше кода. Поэтому я присвоил возвращаемое значение функции подкачки строке и получил измененные значения строки. после присвоения возвращенного значения я получил перестановочные значения строки.
источник
Буду выкладывать ставить что то подобное
1419358369 1419358369
103056 65078777
Цель неизменяемого объекта состоит в том, что его значение не должно изменяться после назначения. Он будет возвращать новый объект каждый раз, когда вы пытаетесь изменить его в зависимости от реализации. Примечание: Stringbuffer вместо string может использоваться, чтобы избежать этого.
К вашему последнему вопросу :: у вас будет одна ссылка и 2 строки в пуле строк. За исключением ссылки будет указывать на m! Ss! Ss! Pp!
источник