Строковый литерал Java String и строковый объект - PullRequest
11 голосов
/ 08 ноября 2011

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

Пожалуйста, поправьте меня, если мои объяснения неверны.

String s = "abc";

Если указанная выше строка выполнена, строковый литерал «abc» добавляется в пул строк, если он не существует в пуле. И строковый объект создается в куче, и ссылка s будет указывать на литерал в пуле.

Вопросы:

  1. Этот код создает строковый объект в куче каждый раз, когда он выполняется?
  2. Поддерживает ли строковый литерал только строковые литералы или же строковый объект?
  3. Когда JVM решает, что ей нужно добавить строковый литерал в пул строк? это решает во время компиляции или во время выполнения?

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

Спасибо.

Ответы [ 4 ]

5 голосов
/ 08 ноября 2011

Нет "буквального пула". Interned Strings - это просто обычные объекты кучи. Они могут оказаться в PermGen, но даже в этом случае они могут быть в конечном итоге собраны мусором.

Файл класса имеет постоянный пул, который содержит литералы String, используемые в классе. Когда класс загружается, из этих данных создаются объекты String, что, вероятно, очень похоже на то, что делает String # intern.

Этот код создает строковый объект в куче каждый раз, когда он выполняется?

Нет. Будет один объект String, который используется повторно. Он был создан при загрузке класса.

Поддерживает ли пул строковых литералов только строковые литералы или также строковый объект?

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

Когда JVM решает, что ей нужно добавить строковый литерал в пул строк? это решает во время компиляции или во время выполнения?

Литералы всегда "объединены". Для других строк необходимо, чтобы к ним вызывался "intern". Таким образом, решение принимается во время компиляции.

4 голосов
/ 08 ноября 2011

Цитирование документации для String.intern () ( выделение шахты )

Все литеральные строки и строковые константные выражения интернированы.Строковые литералы определены в §3.10.5 Спецификации языка Java


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

Когда вызывается метод intern, если пул уже содержит строку, равную этому объекту String, как определено методом equals (Object), возвращается строка из пула.В противном случае этот объект String добавляется в пул и возвращается ссылка на этот объект String.


Таким образом,

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

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

Поддерживает ли строковый литерал только строковые литералы или также строковый объект?

Нет литеральных объектов.Буквенные строковые выражения при преобразовании хранятся как обычные String объекты. Также пул содержит все интернированные строковые объекты.И неявные (с использованием строкового литерального выражения), и явные (путем вызова .intern() для String объекта).

Когда JVM решает, что необходимо добавить строковый литерал в пул строк?это решает во время компиляции или во время выполнения?

Я не уверен.

1 голос
/ 08 ноября 2011

Этот код создает строковый объект в куче каждый раз, когда он выполняется?

Нет.После создания в буквальном пуле.То же самое упоминается снова и снова.

Поддерживает ли строковый литерал только строковые литералы или также строковый объект?

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

Когда JVM решает, что ей нужно добавить строковый литерал в пул строк?решает ли он во время компиляции или во время выполнения?

Всякий раз, когда JVM встречает выражения типа

String str="Hello"; (string literal) or
String str="Hel" + "lo"; (string constant expression).

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

Проверьте эту ссылку.

1 голос
/ 08 ноября 2011

Я думаю, что вам чего-то не хватает: внутренний пул строк только содержит объекты String. Литералы не являются каким-то особым объектом; во время выполнения они являются просто еще одним объектом String.

Кроме того, вы можете интернировать любую строку, которую хотите, используя String.intern(); оно не должно происходить из литерала.

Итак, что касается ваших вопросов:

  1. Нет, при загрузке класса будет выделен один объект String.
  2. Он не поддерживает никаких литералов , а содержит строковые объекты, которые были интернированы. Обычно они происходят из литералов, но в действительности это может быть любое константное выражение во время компиляции (String constant = "abc" + "def" приведет к одному объекту String "abcdef" во время выполнения).
  3. Они скомпилированы в файл класса. Поэтому они определяются во время компиляции, но, очевидно, сами объекты создаются во время выполнения.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...