Что значит неизменный?


104

Если строка неизменяема, значит ли это, что .... (предположим, JavaScript)

var str = 'foo';

alert(str.substr(1)); // oo

alert(str); // foo

Означает ли это, что при вызове методов для строки он вернет измененную строку, но не изменит исходную строку?

Если строка была изменяемой, значит ли это, что вторая alert()тоже вернется oo?

Ответы:


105

Это означает, что после создания экземпляра объекта вы не можете изменить его свойства. В первом предупреждении вы не меняете foo. Вы создаете новую строку. Вот почему во втором предупреждении вместо oo будет отображаться «foo».

Означает ли это, что при вызове методов для строки он вернет измененную строку, но не изменит исходную строку?

Да. После создания строки ничто не может изменить ее. Это не означает, что вы не можете присвоить strпеременной новый строковый объект . Вы просто не можете изменить текущий объект, на который ссылается str.

Если строка была изменяемой, означает ли это, что второй метод alert () также вернет oo?

Технически нет, потому что метод подстроки возвращает новую строку. Если сделать объект изменяемым, метод не изменится. Сделать его изменяемым означает, что технически вы можете сделать так, чтобы подстрока изменяла исходную строку, а не создавала новую.


Эта же строка, если она изменена и назначена, обновит строку var str = 'foo'; str = str.substr (1)); // oo alert (str); // oo
Ashwin G

Как насчет кода ниже. Строковое значение теперь изменено. var name = "Сантош"; console.log (name.substr (0,2)); var name = "kumar" console.log (имя); Как он все еще неизменен
Сантош

98

На более низком уровне неизменность означает, что память, в которой хранится строка, не будет изменена. После создания строки "foo"для хранения значения выделяется некоторая память "foo". Эта память не будет изменена. Если вы измените строку, скажем, будет substr(1)создана новая строка и выделена другая часть памяти, которая будет храниться "oo". Теперь у вас есть две строки в памяти "foo"и "oo". Даже если вы больше не собираетесь использовать "foo"его, он останется, пока не соберет мусор.

Одна из причин, почему строковые операции сравнительно дороги.


1
Числа тоже неизменны.
RN Kushwaha

3
привет с 2015 года !! «На более низком уровне неизменяемость означает, что память, в которой хранится строка, не будет изменена» - это слишком ограничительно и звучит неправильно. Неизменяемость касается только пользовательского пространства, виртуальная память может быть изменена по желанию распределителя памяти, как только будут сохранены инварианты языковой спецификации.
zerkms

2
Этот ответ более логичен, чем принятый ответ.
Ejaz Karim

Но я могу делать как var str = 'foo'; я могу изменить через str = 'bar'. Значение str было изменено таким образом, верно?
Hacker

@Hacker Нет. Вы присвоили новую строку переменной, указывающей на новое место в памяти.
deceze

13

Неизменяемый означает то, что нельзя изменить или модифицировать.

Поэтому, когда вы присваиваете значение строке, это значение создается с нуля, а не заменяется. Таким образом, каждый раз, когда одной и той же строке присваивается новое значение, создается копия. Так что на самом деле вы никогда не меняете исходное значение.


9

Я не уверен насчет JavaScript, но в Java строки делают дополнительный шаг к неизменности с помощью «String Constant Pool». Строки можно создавать с помощью строковых литералов ( "foo") или с помощью Stringконструктора класса. Строки, построенные с помощью строковых литералов, являются частью пула констант строк, и один и тот же строковый литерал всегда будет одним и тем же адресом памяти из пула.

Пример:

    String lit1 = "foo";
    String lit2 = "foo";
    String cons = new String("foo");

    System.out.println(lit1 == lit2);      // true
    System.out.println(lit1 == cons);      // false

    System.out.println(lit1.equals(cons)); // true

В приведенном выше примере оба lit1и lit2построены с использованием одного и того же строкового литерала, поэтому они указывают на один и тот же адрес памяти; lit1 == lit2приводит к тому true, что это один и тот же объект.

Однако consсоздается с использованием конструктора класса. Хотя параметр является той же строковой константой, конструктор выделяет новую память для cons, что означает, что consэто не тот же объект, что lit1и lit2, несмотря на то, что он содержит те же данные.

Конечно, поскольку все три строки содержат одни и те же символьные данные, использование equalsметода вернет true.

(Конечно, оба типа построения строк неизменяемы)


3

Неизменяемый означает, что значение нельзя изменить. После создания строковый объект не может быть изменен как неизменный. Если вы запрашиваете подстроку строки, создается новая строка с запрошенной частью.

Использование StringBuffer при манипулировании строками вместо этого делает операцию более эффективной, поскольку StringBuffer хранит строку в массиве символов с переменными для хранения емкости массива символов и длины массива (String в форме массива символов)


3

Учебное определение изменчивости может быть изменено или изменено. В программировании мы используем это слово для обозначения объектов, состояние которых может меняться с течением времени. Неизменяемое значение - это полная противоположность - после того, как оно было создано, оно никогда не может измениться.

Если это кажется странным, позвольте мне напомнить вам, что многие из значений, которые мы используем постоянно, на самом деле неизменны.

var statement = "I am an immutable value";
var otherStr = statement.slice(8, 17);

Думаю, никто не удивится, узнав, что вторая строка никоим образом не меняет строку в выражении. Фактически, никакие строковые методы не изменяют строку, над которой они работают, все они возвращают новые строки. Причина в том, что строки неизменяемы - они не могут измениться, мы можем создавать только новые строки.

Строки - не единственные неизменяемые значения, встроенные в JavaScript. Числа тоже неизменны. Можете ли вы даже представить себе среду, в которой оценка выражения 2 + 3 изменяет значение числа 2? Это звучит абсурдно, но мы постоянно поступаем так с нашими объектами и массивами.


2

От строк к стопкам ... простой для понимания пример из блога Эрика Липперта :

Поиск пути с помощью A * в C # 3.0, часть вторая ...

Изменяемый стек, такой как System.Collections.Generic.Stack, явно не подходит. Мы хотим иметь возможность взять существующий путь и создать из него новые пути для всех соседей его последнего элемента, но добавление нового узла в стандартный стек изменяет стек. Нам пришлось бы сделать копии стека, прежде чем отправлять его, что глупо, потому что тогда мы будем дублировать все его содержимое без необходимости.

Неизменяемые стеки не имеют этой проблемы. Нажатие на неизменяемый стек просто создает совершенно новый стек, который связывается со старым как его хвост. Поскольку стек неизменен, нет опасности, что какой-то другой код придет и испортит содержимое хвоста. Вы можете продолжать использовать старый стек, сколько душе угодно.

Чтобы глубже понять неизменность, прочитайте сообщения Эрика, начинающиеся с этого:

Неизменяемость в C #, часть первая: виды неизменяемости


Эта цитата содержит странное утверждение - структура данных стека (на самом деле несколько стеков с разделением хвостов) в целом является изменяемой структурой - каждое нажатие или выталкивание меняет структуру. Неизменяемы только отдельные элементы. В принципе, у вас может быть такая же структура, но с изменяемыми элементами. Это происходит в некоторых вариантах отменяемого поиска объединения IIRC. Неизменяемость имеет большие преимущества, но совместное использование части или всей структуры данных в качестве оптимизации вполне возможно с изменяемыми. Даже если вам нужна очевидная неизменяемость для других ссылок, вы всегда можете копировать при записи по мере необходимости.
Steve314 08

0

Один из способов понять эту концепцию - посмотреть, как javascript обрабатывает все объекты, то есть по ссылке. Это означает, что все объекты изменяются после создания экземпляра, это означает, что вы можете добавить объект с новыми методами и свойствами. Это важно, потому что если вы хотите, чтобы объект был неизменным, объект не может измениться после создания экземпляра.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.