Вопросы о пуле строк Java
Рассмотрим этот код:
String first = "abc";
String second = new String("abc");
При использовании new
ключевое слово, Java создаст abc
String
опять верно? Будет ли это храниться в обычной куче или String
бассейн? Как много String
s закончится в String
бассейн?
7 ответов
Если вы используете new
ключевое слово, новый String
объект будет создан. Обратите внимание, что объекты всегда находятся в куче - пул строк не является отдельной областью памяти, отдельной от кучи.
Пул строк похож на кеш. Если вы делаете это:
String s = "abc";
String p = "abc";
тогда компилятор Java достаточно умен, чтобы сделать только один String
объект и s
а также p
оба будут ссылаться на тот же объект String. Если вы делаете это:
String s = new String("abc");
тогда будет один String
объект в пуле, тот, который представляет буквальное "abc"
и будет отдельный String
объект, не входящий в пул, который содержит копию содержимого объекта пула. поскольку String
является неизменным в Java, вы ничего не получаете, делая это; призвание new String("literal")
никогда не имеет смысла в Java и является излишне неэффективным.
Обратите внимание, что вы можете позвонить intern()
на String
объект. Это положит String
Объект в пуле, если он еще не существует, и вернуть ссылку на объединенную строку. (Если он уже был в пуле, он просто возвращает ссылку на объект, который уже был там). См. Документацию API для этого метода для получения дополнительной информации.
Смотрите также String interning (Википедия).
В байт-коде первое назначение:
Код: 0: ldC# 2; // Строка abc 2: astore_1
тогда как второе:
3: новый № 3; // класс java/lang/String 6: дуп 7: ldC# 2; // Строка abc 9: invokeespecial #4; // Метод java/lang/String."":(Ljava/lang/String;)V
Таким образом, первый находится в пуле (в позиции № 2), а второй будет храниться в куче.
РЕДАКТИРОВАТЬ
Так как CONSTANT_String_info
сохранить индекс как U2 (16 бит, без знака), который может содержать пул при макс. 2**16
знак равно 65535
Рекомендации. В случае, если вам небезразлично, здесь больше ограничений JVM.
Каждый раз, когда ваш код создает строковый литерал
например:
String str="Hello"; (string literal)
JVM сначала проверяет пул строковых литералов. Если строка уже существует в пуле, возвращается ссылка на объединенный экземпляр. Если строка не существует в пуле, создается новый объект String, а затем помещается в пул. Java может сделать эту оптимизацию, поскольку строки неизменяемы и могут использоваться совместно, не опасаясь повреждения данных.
String strObject = new String("Java");
а также
String strLiteral = "Java";
Оба выражения дают вам объект String, но между ними есть небольшая разница. Когда вы создаете объект String с помощью оператора new(), он всегда создает новый объект в динамической памяти. С другой стороны, если вы создаете объект с использованием строкового литерального синтаксиса, например "Java", он может вернуть существующий объект из пула строк (кэш объекта String в пермском пространстве, который теперь перемещен в пространство кучи в недавнем выпуске Java), если он уже существует.
Единственный раз, когда вы должны использовать новую строку (foo), это когда вы хотите разбить ==, что является нечетным случаем, или когда foo является подстрокой гораздо большей строки с ограниченным временем жизни, такой как
String mystring;
{
String source = getSomeHeinouslyLargeString();
mystring = new String(source.substring(1,3));
}
Хотя поздно, может быть полезно для кого-то еще сталкивался с этим:
String first = "abc";
//One instance object in pool created. Instance variable “first” refers/points to pooled object
String second = new String("abc");
//One instance object in heap created. Object in pool creation step will be skipped on account of first statement.
Всего будет создано 2 экземпляра объекта. Один в бассейне и другой в куче
Детальное объяснение
String first = "abc";
Здесь строковый объект с содержимым "abc", созданным в пуле. Переменная экземпляра "first" будет указывать на объект пула с содержимым "abc".
String second = new String ("abc");
Здесь еще один строковый объект с содержимым "abc" будет создан в куче. Переменная экземпляра "second" будет указывать на объект кучи с содержимым "abc". Строковый объект с созданием содержимого "abc" в пуле будет пропущен из-за 1-го оператора. Причина ниже.
Причины
Если предполагаемый предыдущий оператор (String first = "abc";) отсутствует с таким же содержимым, то обычно с ключевым словом "new" будет создано 2 строковых объекта, один в куче (вне пула), а другой в пуле (область поднабора). кучи). Также переменная экземпляра "second" должна указывать только на объект кучи, независимо от того, находятся объекты в пуле или нет.
Теперь из-за наличия предыдущего оператора (String first = "abc";) с тем же содержимым, что и в новой строке ("abc"), в пуле сохраняется только один объект (с содержимым "abc"). Таким образом, из-за 1-го оператора у второго оператора будет создан только 1 объект вместо 2, и этот объект находится в куче. Создание объекта пула будет пропущено.
//Additional Test on the concept
System.out.println(first==second); //returns false. Because first points to pool object while second points to heap object. And both objects are different (on account of different memory locations).
second = second.intern(); //After interning, second now points to pool object. Note: intern is used so that reference variable points to pool area object and not heap object. Clearly it is applicable when we use new keyword.
System.out.println(first==second); //returns true. Because now both first and second objects now points to same pool object.
String first = "abc";
String second = new String("abc");
В первом случае в пуле будет создан только один объект. Во втором случае два объекта создадут один в пуле (если он ранее не существовал в пуле) и один в куче.
Когда вы передаете любое значение с двойной кавычкой, например, "abc", вы создаете объект в пуле и передаете его строковому конструктору для создания нового объекта с тем же значением в куче.
Если вы видели строковый конструктор, вы можете видеть, что он принимает строку. Что это за строка? Перед созданием что это за строковый объект. Это ничего, кроме объекта, хранящегося в пуле String Constant.