Строки одинакового значения в Java? - PullRequest
11 голосов
/ 02 июля 2011

быстрый и запутанный вопрос.Если класс A и класс B имеют это внутри: -

String name="SomeName"; 

и оба класса созданы, верно, что оба экземпляра ссылаются на одну и ту же ячейку памяти переменной «name», скажем, когда мы делаем это objA.имя или objB.name?который имеет значение «SomeName» и поскольку String является неизменным, несколько экземпляров обоих классов одной и той же JVM неоднократно используют одну и ту же переменную?Я где-то читал в Интернете, что, если не используется

String example=new String("something"); 

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

Ответы [ 5 ]

25 голосов
/ 02 июля 2011

Да, если вы создаете две строки, такие как:

String a = "Hello";
String b = "Hello";

Они будут точно таким же объектом. Вы можете проверить это самостоятельно, выполнив

System.out.println (a == b);

Если это один и тот же объект, то их внутренняя ссылка на массив символов будет точно такой же.

Теперь, если вы сделали String c = "Hell" + "o";, у него не было бы той же ссылки, так как она была бы (внутренне) построена с использованием StringBuilder.

Здесь много полезной информации здесь .

Соответствующие разделы имеют (Примечание: с этого сайта скопировано следующее):


Как уже упоминалось, существует два способа создания строки: неявное конструирование путем назначения литерала String или явное создание объекта String с помощью оператора new и конструктора. Например,

String s1 = "Hello";              // String literal
String s2 = "Hello";              // String literal
String s3 = s1;                   // same reference
String s4 = new String("Hello");  // String object
String s5 = new String("Hello");  // String object

Strings

Java разработала специальный механизм для хранения литералов String - в так называемом общем пуле строк. Если два строковых литерала имеют одинаковое содержимое, они будут использовать одни и те же места хранения в общем пуле. Этот подход принят для сохранения памяти для часто используемых строк. С другой стороны, объект String, созданный с помощью нового оператора, хранится в куче. Каждый объект String в куче имеет свое собственное хранилище, как и любой другой объект. В куче нет общего хранилища, даже если два объекта String имеют одинаковое содержимое. Вы можете использовать метод equals () класса String для сравнения содержимого двух строк. Вы можете использовать оператор реляционного равенства '==' для сравнения ссылок (или указателей) двух объектов. Изучите следующие коды:

s1 == s1;         // true, same pointer
s1 == s2;         // true, s1 and s1 share storage in common pool
s1 == s3;         // true, s3 is assigned same pointer as s1
s1.equals(s3);    // true, same contents
s1 == s4;         // false, different pointers
s1.equals(s4);    // true, same contents
s4 == s5;         // false, different pointers in heap
s4.equals(s5);    // true, same contents

Изменить, чтобы добавить: Запустите эту SSCE, чтобы проверить равенство ссылок между двумя константными строками в разных классах:

class T {
  String string = "Hello";

  public static void main(String args[]) {
    T t = new T();
    T2 t2 = new T2();
    System.out.println(t.string == t2.string);
  }
}


class T2 {
  String string = "Hello";
}

распечатывает true.

2 голосов
/ 02 июля 2011

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

1 голос
/ 02 июля 2011

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

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

0 голосов
/ 16 ноября 2015

Я бы добавил еще одну деталь ко всем решениям выше. Интернирование строк - это просто оптимизация компилятора Java / C #. На это не стоит полагаться, так как в обоих случаях его можно отключить.

Он также может вести себя по-разному в разных реализациях компиляторов / виртуальных машин

0 голосов
/ 02 июля 2011

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

Строка, созданная во время выполнения (например, "abc" + "xyz" или new String ("abc") ) не будет интернирована, поэтому указатель обычно быть уникальный. (Но учтите, что оптимизирующий компилятор может объединить "abc" + "xyz" в один литерал "abcxyz" , что приводит к интернированному значению.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...