Что делает неизменный средний?

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

var str = 'foo';

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

alert(str); // foo

Это означает, когда вызывающие методы для строки, это возвратит измененную строку, но это не поменяет начальную струну?

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

103
задан alex 8 July 2010 в 10:32
поделиться

5 ответов

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

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

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

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

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

104
ответ дан 24 November 2019 в 04:17
поделиться

Неизменяемый означает то, что не может быть изменено или изменено.

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

13
ответ дан 24 November 2019 в 04:17
поделиться

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

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

97
ответ дан 24 November 2019 в 04:17
поделиться

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

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

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

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

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

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

2
ответ дан 24 November 2019 в 04:17
поделиться

Я не уверен насчет JavaScript, но в Java строки делают дополнительный шаг к неизменяемости с помощью "Пула строковых констант". Строки могут быть созданы с помощью строковых литералов ("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.

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

9
ответ дан 24 November 2019 в 04:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: