Создание литеральной строки против создания объекта String - PullRequest
7 голосов
/ 29 ноября 2011

Сколько объектов String создано

Я учусь в SCJP, я не могу разобраться с этой проблемой Струн. Кажется, я вижу несколько возможных ответов в зависимости от того, как я смотрю на вопрос.

Сколько будет создано строковых объектов в следующей инициализации?

String s1 = "A" + "B" + "C" + "D";
System.out.println(s1)

Первоначально я думал о 5 объектах, т.е.

"A"
"B"
"C"
"D"
"ABCD"

Но, подумав об этом, я не совсем уверен, потому что, например, компилятор объединит "A" + "B" как один объект? т.е. создание 7 объектов?

"A"
"B"
"C"
"D"
"AB"
"ABC"
"ABCD" 

Кроме того, сколько объектов будет создано, если код был изменен на

String s1 = new String("A" + "B" + "C" + "D");
System.out.println(s1);

И, наконец, как насчет:

String s1 = "A";
String s2 = new String("A");

В приведенном выше примере я думаю, что будут созданы только 2 объекта

object 1 - "A"
object 2 - a String object that refers to the "A" object above.

Это правильно или они не будут связаны? то есть объект, на который ссылаются из пула констант, будет отличаться от объекта, на который ссылается ссылка s2.

Спасибо

Редактировать

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

Редактировать

Глядя на ответ Джона, я мог совершенно неправильно понять, как создаются объекты. Я знаю, что String создается только один раз в пуле констант, и он используется повторно, но я не уверен в процессе, который проходит, когда строится 'final' строка. Вот раздел из книги, которую я читаю, которая, кажется, предполагает создание временных объектов, что является полной противоположностью ответам здесь. (Или, возможно, книга не права, или я неправильно понял книгу)

Пример кода

String s1 = "spring ";  
String s2 = s1 + "summer ";  
s1.concat("fall ");  
s2.concat(s1);  
s1 += "winter";  
System.out.println(s1 + " " + s2);

Вопрос был

Какой вывод? Для дополнительного кредита, сколько объектов String и как многие ссылочные переменные были созданы до оператора println .

И ответ

Результат этого фрагмента кода spring water spring summer. Там две ссылочные переменные, s1 и s2. Всего было восемь Строковые объекты, созданные следующим образом: «весна», «лето» (потеряно), «весна» лето "," падает "(потеряно)," весна осень "(потеряно)," весна лето весна " (потерян), «зима» (потерян), «весна зима» (на данный момент «весна» потерял). Только два из восьми объектов String не потеряны в этом процесс

Спасибо

Ответы [ 3 ]

13 голосов
/ 29 ноября 2011

Компилятор объединит все "A" + "B" + "C" + "D" в одну константу - так что в вашем первом примере только одна строка в итоге будет создана на всех . Эта же строка будет использоваться повторно, если вы выполняете один и тот же код несколько раз. Константа помещается в файл класса, и когда класс загружается, ВМ проверяет, есть ли в пуле строк уже равная строка, поэтому она будет использовать ее повторно, даже если у вас один и тот же код в нескольких классах.

Вы можете проверить, что в пуле констант в классе есть только одна строка с помощью javap:

javap -v Test

Constant pool:
   #1 = Methodref   #6.#17     //  java/lang/Object."<init>":()V
   #2 = String      #18        //  ABCD
   #3 = Fieldref    #19.#20    //  java/lang/System.out:Ljava/io/PrintStream;

Однако, здесь:

String s1 = "A";
String s2 = new String("A");

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

Так, например, этот метод:

public static void foo() {
    for (int i = 0; i < 5; i++) {
        String s1 = "A";
        String s2 = new String("A");
    }
}

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

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

Сколько объектов создано?

String s1 = "A" + "B" + "C" + "D";
System.out.println(s1)

Один или нет. Это сокращается до одного строкового литерала, который может быть уже загружен.

String s1 = new String("A" + "B" + "C" + "D");
System.out.println(s1);

Это всегда создает дополнительный объект.

Кстати: строка обычно состоит из двух объектов: String и char[], в которые она заключена.

2 голосов
/ 29 ноября 2011
String s1 = "A" + "B" + "C" + "D";

Компилятор создаст только один строковый литерал "ABCD" и поместит его в пул строк. Будет создан один объект (тот, что находится в пуле строк).


String s1 = new String("A" + "B" + "C" + "D");

То же самое здесь, за исключением того, что вы копируете его из строкового литерала. Итак, 2 объекта будут созданы здесь. Один на new и один в Струнном пуле.


String s1 = "A";
String s2 = new String("A");

То же самое здесь, "A" будет константой в пуле строк. Конструктор скопирует его. Итак, здесь будут созданы два объекта.

...