2014-02-07 4 views
1

, если я создать строковый объект, как, что происходит с новой строкой («») в строковой константе бассейна

String s=new String("Stackoverflow"); 

будет создан объект Строки только в куче, или это также делает копию в строковой константе бассейна.

Заранее спасибо.

+0

Оба. И то и другое. И то и другое. –

+0

'String x =" Stackoverflow "' будет помещен в постоянный пул, 'String x = new String (" Stackoverflow ")' будет помещен в 'heap', а также' String s = new String ("") ' , – Omoro

+0

Вы должны найти подробный ответ здесь: http://stackoverflow.com/questions/14150628/string-constant-pool-java –

ответ

6

Вы получаете строку только в пул констант, если вы вызываете intern или используете строковый литерал, насколько мне известно.

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

В вашем случае вы также гарантируя, что является строка с содержимым "Stackoverflow" в постоянном бассейне, тот факт, что вы используете строку буквального вообще - но это не будет добавить еще один, если это уже есть. Таким образом, чтобы разделить его:

String x = "Stackoverflow"; // May or may not introduce a new string to the pool 
String y = new String(x); // Just creates a regular object 

Кроме того, в результате вызова new String(...) всегда будет другая ссылка на все предыдущие ссылки - в отличие от использования строкового литерала. Например:

String a = "Stackoverflow"; 
String b = "Stackoverflow"; 

String x = new String(a); 
String y = new String(a); 

System.out.println(a == b); // true due to constant pooling 
System.out.println(x == y); // false; different objects 

Наконец, точные сроки, когда строка добавляется к постоянная бассейну никогда не были для меня ясно, и не имеют это значение для меня. Я бы предположил, что может быть на загрузке класса (все строковые константы, используемые этим классом, загружаются немедленно), но он может потенциально находиться на основе каждого метода. Можно найти одну конкретную реализацию, используя intern(), но для меня это никогда не было очень важно :)

+1

Да, но он использовал строковый литерал. Литерал идет в постоянном пуле, и новый объект переходит в кучу. –

+3

@DavidWallace: Но использование литерала само по себе не добавляет к постоянному пулу - оно гарантирует, что значение равно * в * постоянном пуле, но оно уже может быть там. Я разъяснил это в редактировании. –

+0

Я думаю, что формулировка вопроса подразумевает, что литерал не был в постоянном пуле для начала. –

5

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

Если вы сделали String s = "Stackoverflow", то s будет содержать ссылку на экземпляр в пуле, также есть методы, позволяющие добавить String s в пул после того, как они были созданы.

+1

'' stackoverflow '' будет в пуле, 's' не будет. – assylias

+0

Да, поэтому мы получаем две копии '' stackoverflow'' - буквальную в постоянном пуле, плюс 's' в куче. –

+0

Omoro правильный. В этом случае «новая строка» создается из константы String. Таким образом, константа добавляется в пул строк, из этой константы создается новый объект String в куче. –

2

Новая строка создается в куче, а НЕ в пуле строк.

Если вы хотите, чтобы новая строка String находилась в пуле строк, вам необходимо указать intern(); то есть

String s = new String("Stackoverflow").intern(); 

... кроме того, что будет возвращен строковый литерал, который вы начали с!

String s1 = "Stackoverflow"; 
String s2 = new String(s1); 
String s3 = s2.intern(); 

System.out.println("s1 == s2 is " + (s1 == s2)); 
System.out.println("s2 == s3 is " + (s2 == s3)); 
System.out.println("s1 == s3 is " + (s1 == s3)); 

должен напечатать

s1 == s2 is false 
s2 == s3 is false 
s1 == s3 is true 

И быть педантичным, то String в s не String, который был создан с помощью выражения new String("StackOverflow"). То, что делает intern(), - это поиск целевого объекта в пуле строк. Если в пуле уже есть String в строке equal(Object), , что - это то, что возвращается в результате. В этом случае мы можем гарантировать, что в пуле строк уже будет объект; т. е. объект String, который представляет значение литерала.

1

В куче будет создан обычный объект java и будет иметь ссылку s тип String. И будет строковый литерал в String Constant Pool. Оба - две разные вещи.

0

Мой ответ ДА!

Проверьте следующий код первого:

String s0 = "Stackoverflow"; 
String s1 = new String("Stackoverflow"); 
String s2 = s1.intern(); 

System.out.println(s0 == s1); 
System.out.println(s1 == s2); 
System.out.println(s0 == s2); 

//OUTPUT: 
false 
false 
true 

s0 содержат ссылку в струнной бассейне, в то время как new String(String original) всегда будет строить новый экземпляр. intern() метод String вернет ссылку в пуле строк с тем же значением.

Теперь вернемся к вашему вопросу:

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

Поскольку вы уже писали строковая константа "Stackoverflow" и передать его в String конструктор, поэтому, на мой взгляд, он имеет тот же семантический как:

String s0 = "Stackoverflow"; 
String s1 = new String(s0); 

что означает, что будет копией в постоянной Струнный пул, когда код оценивается.

Но, если вы строите String объект с помощью следующего кода:

String s = new String("StackoverflowSOMETHINGELSE".toCharArray(),0,13); 

не будет копией "Stackoverflow" в постоянном бассейне.

Смежные вопросы