Как Java обрабатывает объекты String в памяти?

Мне задали этот вопрос:

String s = "abc"; // creates one String object and one
          // reference variable
In this simple case, "abc" will go in the pool and s will refer to it.
String s = new String("abc"); // creates two objects,
                 // and one reference variable*

Основываясь на приведенных выше сведениях, сколько объектов String и сколько ссылочных переменных было создано до оператора println в приведенном ниже коде?

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

Мой ответ был результатом этого фрагмента кода весна зима весна лето

Есть две ссылочные переменные, s1 и s2. Всего было создано восемь объектов String: «весна», «лето» (потеряно), «весна лето», «осень» (потеряно), «весна-осень» (потеряно), «весна-лето-весна» (потеряно). ), "зима" (утрачено), "весна-зима" (в этом месте "весна" утеряно).

В этом процессе не теряются только два из восьми объектов String.

Это правильно?


person coder_15    schedule 25.01.2012    source источник
comment
Полезно знать: stackoverflow.com/ вопросов/7663252/ Обратите внимание, что мой ответ на этот вопрос был неправильным...   -  person Marsellus Wallace    schedule 26.01.2012


Ответы (4)


Ответ: 2 ссылки и 8 объектов.

String s1 = "spring "; //One reference and 1 object in string pool. (if it didn't exist already)

String s2 = s1 + "summer "; //Two references and 3 objects

s1.concat("fall "); //Two references and 5 objects

s2.concat(s1); //Two references and 6 objects

s1 += "winter "; //Two references and 8 objects

System.out.println(s1 + " " + s2);

Теперь ваш вопрос: Как Java обрабатывает объекты String в памяти?

Java предоставляет два способа создания объекта класса String.

  1. Строка str1 = "ОднаСтрока";

В этом случае JVM ищет в пуле строк, чтобы увидеть, существует ли уже эквивалентная строка. если да, возвращает ссылку на то же самое. если нет, добавляет его в пул строк и возвращает ссылку. Таким образом, новый объект может быть создан ИЛИ не может быть создан.

  1. Строка str1 = новая строка ("OneString");

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

Вы также можете поместить строку в пул:

Вы можете вызвать метод intern() для объекта String. Это поместит объект String в пул, если его там еще нет, и вернет ссылку на строку в пуле. (Если он уже был в пуле, он просто возвращает ссылку на объект, который там уже был).

Вы можете посмотреть следующие ссылки:

Что такое пул строк Java и чем s отличается от новых строк?

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

person Azodious    schedule 25.01.2012

Строки в java неизменяемы. Существует выделенный массив символов и некоторая окружающая информация, такая как смещение и длина. Если вы используете строковые литералы для инициализации ваших строк, компилятор попытается оптимизировать и создаст только один строковый объект для каждого литерала - это возможно, потому что они неизменяемы.

Если вы выполняете конкатенацию или + для строк, то новая строка будет выделена, а данные скомпилированы вместе (с потерей производительности.

В отличие от этого, создание подстроки из строки практически бесплатно - никакие данные не будут скопированы.

person Konstantin Pribluda    schedule 25.01.2012

String s = "abc"; // creates one String object and one 
                 // reference variable 

Создает один строковый объект, только если этот объект еще не представлен в пуле строковых констант.

String s = new String("abc"); // creates two objects,
                              // and one reference variable*  

Это фактически создает только один объект в куче. Он добавляет этот объект в пул тогда и только тогда, когда для этого объекта String вызывается метод intern().

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

Ваше объяснение выглядит нормально, за исключением того, что у вас есть еще одна строка в System.out.println().:-)
Когда вы говорите (потерял), это на самом деле означает, что это больше не живой объект (ссылка отсутствует на куча).

person Syam    schedule 25.01.2012

Выглядит правильно. Кстати, это экзаменационный вопрос SCJP.

concat возвращает новую строку, она теряется. Первый s1 заменен на «весна-зима».

Две вещи, которые вы должны знать о строках в Java:

  • Строки неизменяемы (как вы уже объяснили)
  • Строки могут находиться в пуле строк. Не каждый раз, когда вы пишете «Лето», создается совершенно новый String ist, неизменяемое «Лето» может выйти из пула (зависит от JVM, но для Oracle это так). См. также: http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/String.html#intern()

Ура Кристиан

person Christian    schedule 25.01.2012
comment
Не могли бы вы подробнее прокомментировать Не каждый раз, когда вы пишете новую строку (лето), создается совершенно новая строка? Используя новый, должен быть создан объект new java.lang.String (т. е. две строки не совпадают при сравнении их с помощью ==). Однако эти два отдельных экземпляра String могут совместно использовать базовый массив char[] (при определенных условиях). - person Arnost Valicek; 25.01.2012
comment
Да, я набрал быстро. Вы правы, объект String построен - я просто имел в виду, что самой String может не потребоваться больше памяти, потому что она находится в пуле строк. См. также: документы. oracle.com/javase/1.4.2/docs/api/java/lang/ - person Christian; 25.01.2012