Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Хранение неизменяемости Java String при изменении объекта String

Автор вопроса: JiteshОтветов: 2

Я понял, что если строка инициализируется литералом, ей выделяется место в пуле строк, и если она инициализируется новым ключевым словом, она создает объект строки. Но меня смущает случай, который написан ниже.

Мой вопрос: что, если строка создается с новым ключевым словом, а затем ее значение обновляется литералом?

E.g.

String s = new String("Value1");  -- Creates a new object in heap space

то что, если написать следующее утверждение, как показано ниже.

s = "value2";

Итак, мой вопрос:

1 Будет ли он создавать строковый литерал в пуле строк или обновлять значение этого объекта?

2 Если он создаст новый литерал в пуле строк, что произойдет с существующим в настоящее время объектом? Будет ли оно уничтожено или будет там, пока не вызовут сборщик мусора.

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

Будет ли он сразу освобождать место из кучи после назначения литерала?

Кто-нибудь может объяснить, что и какое значение переходит от первого оператора ко второму, и что произойдет с областью памяти (кучей и пулом строк).

  • Ключ к вашему вопросу - s не является объектом. Это ссылка на объект. Вы изменили ссылку, но не изменили здесь никаких объектов. Dmitry Zaytsev 14.09.2015
  • Также обратите внимание, что объекты String неизменяемы. Следовательно, вы не можете обновить значение объекта String (напрямую. Отражение можно использовать для нарушения неизменности). В вашем конкретном случае строка 'value1', которая находится в куче, будет иметь право на сборщик мусора, как только s будет переназначено. Строковый литерал Value1 будет иметь право на сборщик мусора, когда загрузчик класса, загрузивший класс, в котором определен этот литерал, получит сборщик мусора. TheLostMind 14.09.2015
  • @DmitryZaitsev Но, согласно ссылке, из которой я прочитал, если она инициализирована новым ключевым словом, она создаст объект в куче. Итак, есть пространство, занимаемое объектом. Итак, что произойдет с этим пространством, если ему будет назначен литерал (которого нет в куче). Jitesh 14.09.2015
  • @TheLostMind утверждение (s=value2;) действительно (без ошибок компиляции или выполнения), оно позволяет обновить значение s. Так что же будет с пространством объектов? Jitesh 14.09.2015
  • После изменения s = "value2"; объект, созданный с помощью new String("Value1");, будет иметь право на сборку мусора. Pshemo 14.09.2015
  • Я имею в виду тот, который хранится в s (тот, который явно создан с помощью оператора new). Pshemo 14.09.2015

javastringoopimmutabilityheap

Ответы

Ответ 1 · рейтинг 9 · Willem Van Onsem

Изменение Strings

значение не обновляется при запуске

s = "value2";

В Java, за исключением примитивных типов, все остальные переменные являются ссылками на объекты. Это означает, что только s указывает на новое значение.

Неизменяемость гарантирует, что состояние объекта не может измениться после создания. Другими словами, в Java нет средств для изменения содержимого любого объекта String. Если вы, например, указываете s = s+"a";, вы создаете строку new, которая каким-то образом сохраняет новый текст.

Вывоз мусора

Этот ответ уже содержит подробный ответ. Ниже краткое резюме, если вы не хотите читать полный ответ, но в нем опущены некоторые детали.

По умолчанию объекты new String(...) не интернируются, поэтому применяются обычные правила сборки мусора. Это обычные предметы.

Постоянные строки в вашем коде, которые интернированы, обычно никогда не удаляются, поскольку вполне вероятно, что в конечном итоге вы вернетесь к ним.

Однако в ответе есть примечание о том, что иногда классы динамически (не) загружаются, и в этом случае литералы могут быть удалены из пула.


Чтобы ответить на дополнительные вопросы:

Нет, это было бы не очень эффективно: сборщику мусора необходимо провести анализ того, какие объекты следует удалить. Возможно, вы поделились ссылками на свою старую строку с другими объектами, поэтому не гарантируется, что вы сможете повторно использовать объект. Кроме того, нет ничего плохого в хранении данных, которые больше не нужны, если вам не нужно запрашивать дополнительную память у операционной системы (сравните это со своим компьютером, если вы можете хранить все свои данные на жестком диске). , вам действительно не нужно беспокоиться о бесполезных файлах, с того момента, как вам придется покупать дополнительный диск, вы, вероятно, попытаетесь сначала удалить некоторые файлы). Анализ требует некоторых вычислительных усилий. Как правило, сборщик мусора запускается только тогда, когда ему (почти) не хватает памяти. Так что не стоит сильно беспокоиться о памяти.

Ваша первая строка:

String s = new String("Value1");

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

Теперь, если вы позвоните:

s = "value2";

"value2" является элементом пула строк, он останется там до завершения вашей программы.

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

Ответ 2 · Anil Kumar

Если вам нужно изменить строку, вы всегда можете создать новую, содержащую изменения.

  • Java определяет одноранговый класс String, называемый StringBuffer, который позволяет изменять строки.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы