Если jvm
создает string pool
для оптимизации памяти, то почему он создает новый объект каждый раз, когда мы создаем строку, используя ключевое слово new
, даже если оно существует в string pool
?
Почему jvm создает новый строковый объект каждый раз, когда мы создаем строку, используя новое ключевое слово
Ответ 1
... почему Java создает новый Object каждый раз, когда мы создаем строку, используя ключевое слово
new
, даже если оно существует в пуле строк?
Потому что вы прямо сказали это! Оператор new
всегда создает новый объект. JLS 15.9.4 говорит:
"Значение выражения создания экземпляра класса является ссылкой на вновь созданный объект указанного класса. Каждый раз, когда выражение оценивается, создается новый объект."
Для записи почти всегда бывает ошибкой звонить new String(String)
... но в неясных случаях это может быть полезно. Возможно, вам понадобится строка, для которой equals
возвращает true
и ==
дает false
. Вызов new String(String)
даст вам это.
Для более старых версий Java методы substring
, trim
и, возможно, другие String
предоставят вам строку, совместно использующую хранилище с оригиналом. При определенных обстоятельствах это может привести к утечке памяти. Вызов new String(str.trim())
, например, предотвратит утечку памяти за счет создания новой копии обрезанной строки. Конструктор String(String)
гарантирует выделение нового массива поддержки, а также дает вам новый объект String
.
Такое поведение substring
и trim
изменилось в Java 7.
Ответ 2
Чтобы дать примитивный стиль декларации и для разработчиков производительности ввели строковые литералы.
Но когда вы используете ключевое слово new
, то вы явно создаете объекты в куче не в постоянном пуле.
Когда объекты, созданные в куче, не могут разделить эту память друг с другом, и они становятся совершенно незнакомыми, в отличие от постоянного пула.
Чтобы разбить этот барьер между кучей и постоянным пулом String interning
поможет вам.
string interning - это метод хранения только одной копии каждого отдельного строкового значения, которое должно быть неизменным
Помните, что постоянный пул также является небольшой частью кучи с некоторыми дополнительными преимуществами, когда имеется доступ к памяти.
Ответ 3
Когда вы пишете
String str = new String("mystring");
то он создает строковый объект в куче, как и другой объект, который вы создаете. Строковый литерал "mystring" хранится в пуле константных строк.
Из Javadocs:
Пул строк, первоначально пустой, поддерживается конфиденциально class String.
При вызове метода intern, если пул уже содержит строка, равная этому объекту String, определяемая равными (Object) метод, то возвращается строка из пула. В противном случае это Объект String добавляется в пул и ссылка на эту строку объект возвращается.
Отсюда следует, что для любых двух строк s и t s.intern() == t.intern() истинно тогда и только тогда, когда истинны s.equals(t).
Ответ 4
Чтобы использовать пул строк, вам нужно использовать String#intern
вместо нового.
Ответ 5
Следующий объект будет сохранен в пуле строк:
String s = "hello";
И следующий объект будет сохранен в Heap (не в пуле строк):
String s = new String ("hello")
Ответ 6
Обеспечить сбор мусора!. Если вам нужна некоторая строка только один раз, тогда нет смысла хранить ее в памяти (почти навсегда. Это относится к строк в постоянном пуле). Строки, которые не находятся в пуле констант, могут быть GCed как любой другой объект. Таким образом, вы должны хранить только часто используемые строки в пуле констант (используя литералы или интернируя их).
Ответ 7
Строки, созданные в виде строковых литералов (String s = "string";
), хранятся в пуле строк, но строки, созданные путем вызова конструктора String с использованием нового (String s = new String("string");
, не сохраняются в пуле строк.