Строковый постоянный пул - программирование
Подтвердить что ты не робот

Строковый постоянный пул

Как объясняется в этих вопросах Stackoverflow: вопрос 1 и вопрос 2 Я понимаю, что "String литералы" интернирован, когда:

String s = "abc"; 

И что JVM создаст новый объект String вместо того, чтобы использовать существующий из пула строк, когда:

String s = new String("abc");

Однако у меня есть сомнения после прочтения следующих двух подобных утверждений.

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

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

Итак, если мы также помещаем ссылку в непустую память И в память пула, когда мы создаем объект с использованием "нового" и основываясь на приведенных выше определениях. Не следует ли JVM возвращать ту же ссылку, когда мы это делаем?:

String one = new String("test");
String two = "test";

System.out.println(one.equals(two)); // true
System.out.println(one == two);      // false

Потому что при объявлении строкового литерала String three = "test"; он уже будет существовать в пуле? и поэтому должен возвращать ту же ссылку и печатать правду? или предыдущие утверждения означают, что они будут помещены в память пула, но просто пропущены, когда используется оператор new?

4b9b3361

Ответ 1

Возможно, это поможет вашему пониманию:

String literal = "test";
String one = new String(literal);
String two = "test";

System.out.println(literal == two); //true
System.out.println(one == two); //false

В приведенном выше примере:

String one = new String("test");
String two = "test";

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

В этом примере существует ровно два String, созданных со значением "test": тот, который поддерживается в пуле констант и ссылается всякий раз, когда вы используете литерал "test" в выражении, а второй - "новый" оператор и назначен для ссылки one.

Изменить

Возможно, вы смущены этим утверждением:

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

Обратите внимание, что это может быть более четко указано как:

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

Строки помещаются только в пул, если они интернированы явно или используют класс литерала. Поэтому, если у вас есть, например, этот сценарий:

String te = "te";
String st = "st";

String test = new String(te) + new String(st);

тогда, когда a String будет существовать со значением test, указанная строка не будет существовать в пуле, поскольку литерала "test" никогда не происходило.

Ответ 2

    //Creates a new object even if one exists in the pool
    String s1 = new String("Tendulkar");

    // makes a new object string and then the reference is available to the pool
    String s2 = s1.intern();

    //this object is not created but references the address present in the pool
    String s3 = "Tendulkar";

    System.out.print(s1==s2); // results in false
    System.out.print(s2==s3); //very very true !!!

Ответ 3

"abc" помещает объект в пул констант, время компиляции/загрузки класса и new String() создает новый объект во время выполнения. Итак, new String("abc") выполняет оба, но на разных этапах.

Ответ 4

Ваш вопрос:

Итак, если мы также помещаем ссылку в непустую память и в память пула, когда мы создаем объект с использованием "нового" и основываясь на приведенных выше определениях. Должна ли JVM также возвращать ту же ссылку, когда мы это делаем?:

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

Вопросы:

String one = new String("test");
String two = "test";

System.out.println(one.equals(two)); // true
System.out.println(one == two);      // false

выполняют ли предыдущие утверждения, что они будут помещены в память пула, но просто пропущены при использовании нового оператора?

Ответ. Да, ваше предположение верно. Когда программист использует новое ключевое слово, JVM просто игнорирует о пуле строковых констант и создает новую копию в куче. Следовательно, оба адреса не одинаковы.