Я понял, что если строка инициализируется литералом, ей выделяется место в пуле строк, и если она инициализируется новым ключевым словом, она создает объект строки. Но меня смущает случай, который написан ниже.
Мой вопрос: что, если строка создается с новым ключевым словом, а затем ее значение обновляется литералом?
E.g.
String s = new String("Value1"); -- Creates a new object in heap space
то что, если написать следующее утверждение, как показано ниже.
s = "value2";
Итак, мой вопрос:
1 Будет ли он создавать строковый литерал в пуле строк или обновлять значение этого объекта?
2 Если он создаст новый литерал в пуле строк, что произойдет с существующим в настоящее время объектом? Будет ли оно уничтожено или будет там, пока не вызовут сборщик мусора.
Это небольшая строка, если строка состоит, скажем, из тысяч символов, то меня просто беспокоит пространство, которое она занимает. Поэтому мой ключевой вопрос касается пространства.
Будет ли он сразу освобождать место из кучи после назначения литерала?
Кто-нибудь может объяснить, что и какое значение переходит от первого оператора ко второму, и что произойдет с областью памяти (кучей и пулом строк).
Ответ 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). Этот объект является кандидатом на сбор. Если сборщик мусора позже пройдет мимо, он удалит объект из кучи и пометит место как свободное.