Вопросы о пуле строк Java

Рассмотрим этот код:

String first = "abc"; 
String second = new String("abc");

При использовании new ключевое слово, Java создаст abcString опять верно? Будет ли это храниться в обычной куче или String бассейн? Как много Strings закончится в 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.

Другие вопросы по тегам