Строки одинакового значения в Java?

быстрый и запутанный вопрос. Если у класса А и класса B есть внутри них: -

String name="SomeName"; 

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

String example=new String("something"); 

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

Ответ 1

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

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

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

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

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

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

Существует много хорошей информации здесь.

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


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

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

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

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

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