Почему делает добавление “” к Строке, сохраняют память?

Я использовал переменную с большим количеством данных в нем, сказать String data. Я хотел использовать небольшую часть этой строки следующим образом:

this.smallpart = data.substring(12,18);

После нескольких часов отладки (с памятью visualizer) я узнал что поле объектов smallpart помнивший все данные из data, хотя это только содержало подстроку.

Когда я изменил код в:

this.smallpart = data.substring(12,18)+""; 

.. проблема была решена! Теперь мое приложение использует очень мало памяти теперь!

Как это возможно? Кто-либо может объяснить это? Я думаю, что this.smallpart продолжал ссылаться к данным, но почему?

ОБНОВЛЕНИЕ: Как я могу очистить большую Строку тогда? Будет данные =, новая Строка (data.substring (0,100)) делает вещь?

193
задан hsmit 27 January 2010 в 05:57
поделиться

7 ответов

Выполнение следующих действий:

data.substring(x, y) + ""

создает новый (меньший) объект String и отбрасывает ссылку на созданную строку с помощью substring (), тем самым разрешая сборку мусора this.

Важно понимать, что substring () дает окно на существующую String - или, скорее, на массив символов, лежащий в основе исходной String. Следовательно, он будет использовать ту же память, что и исходная строка. В некоторых случаях это может быть выгодно, но проблематично, если вы хотите получить подстроку и избавиться от исходной строки (как вы выяснили).

Для получения дополнительной информации ознакомьтесь с методом substring () в источнике строки JDK.

РЕДАКТИРОВАТЬ: Чтобы ответить на ваш дополнительный вопрос, построение новой строки из подстроки снизит потребление памяти, при условии , что вы сохраняете любые ссылки на исходную строку.

ПРИМЕЧАНИЕ (январь 2013 г.). Вышеупомянутое поведение было изменено в Java 7u6 . Шаблон flyweight больше не используется, и substring () будет работать, как и следовало ожидать.

159
ответ дан 23 November 2019 в 05:28
поделиться

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

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

17
ответ дан 23 November 2019 в 05:28
поделиться

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

Когда вы вызываете метод подстроки, Java не создает Trullly New String, но просто сохраняет ряд символов внутри исходной строки.

Итак, когда вы создали новую строку с этим кодом:

this.smallpart = data.substring(12, 18) + ""; 

Вы фактически создали новую строку при объединении результата с пустой строкой. Вот почему.

5
ответ дан 23 November 2019 в 05:28
поделиться

Если вы посмотрите на источник подстроки (int, int), то увидите, что он возвращает:

new String(offset + beginIndex, endIndex - beginIndex, value);

, где значение - оригинальное char[]. Таким образом, вы получаете новую строку, но с тем же самым, лежащим в основе char[].

Когда вы делаете это, data.substring() + "", вы получаете новую строку с новой, лежащей в основе char[].

На самом деле, ваш случай использования - единственная ситуация, в которой вы должны использовать конструктор String(String):

String tiny = new String(huge.substring(12,18));
28
ответ дан 23 November 2019 в 05:28
поделиться

Как документировано в jwz в 1997:

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

3
ответ дан 23 November 2019 в 05:28
поделиться

Я думаю, что это .smallpart хранится Ссылаясь на данные, но почему?

, потому что java строки состоят из массива Char, начните смещение и длину (и кэшированный хэшкод). Некоторые строковые операции, такие как подстрока () , создайте новый строковый объект, который разделяет массив Char оригинала, и просто имеет различные поля смещения и / или длины. Это работает, потому что массив CHAR из строки никогда не изменяется после того, как оно было создано.

Это может сохранить память, когда многие подстроки относятся к той же базовой строке без репликации перекрытия деталей. Как вы заметили, в некоторых ситуациях он может сохранить данные, которые больше не нужны от мусора.

«правильный» способ исправления этого является новая строка , конструктор , то есть

this.smallpart = new String(data.substring(12,18));

, кстати, общий лучший решение, чтобы избежать очень больших строк в первую очередь, и Обработка любого ввода в меньших кусках, AA несколько КБ за раз.

5
ответ дан 23 November 2019 в 05:28
поделиться

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

   String subtring = string.substring(5,23)

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

   String substring = new String(string.substring(5,23));

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

То, что вы вызываете new String , является полезным напоминанием о том, что вы действительно получаете новую строку, а не ссылку на исходную.

2
ответ дан 23 November 2019 в 05:28
поделиться
Другие вопросы по тегам:

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