В чем разница между «текстом» и новой строкой («текст»)?

В чем разница между этими двумя следующими утверждениями?

String s = "text"; String s = new String("text"); 

9 Solutions collect form web for “В чем разница между «текстом» и новой строкой («текст»)?”

new String("text"); явно создает новый и ссылочно отдельный экземпляр объекта String ; String s = "text"; может повторно использовать экземпляр из пула строковых констант, если он доступен.

Вы очень редко захотите использовать new String(anotherString) . Из API:

String(String original) : Инициализирует вновь созданный объект String так, чтобы он представлял ту же последовательность символов, что и аргумент; Другими словами, вновь созданная строка является копией строки аргумента. Если явная копия оригинала не нужна, использование этого конструктора необязательно, поскольку строки неизменяемы.

Связанные вопросы

  • Строки Java: «String s = новая строка (« глупо »);
  • Строки – это объекты в Java, поэтому почему мы не используем «новое» для их создания?

Какое референциальное различие означает

Изучите следующий fragment:

  String s1 = "foobar"; String s2 = "foobar"; System.out.println(s1 == s2); // true s2 = new String("foobar"); System.out.println(s1 == s2); // false System.out.println(s1.equals(s2)); // true 

== на двух ссылочных типах это сравнение ссылочной идентичности. Два объекта, которые equals , не обязательно == . Обычно неверно использовать == для ссылочных типов; большую часть времени нужно использовать вместо этого.

Тем не менее, если по какой-либо причине вам нужно создать две equals но не == string, вы можете использовать new String(anotherString) . Однако нужно еще раз сказать, что это очень странно, и редко это намерение.

Рекомендации

  • JLS 15.21.3 равенство ссылок Операторы == и! =
  • class Objectboolean Object(equals)

Связанные вопросы

  • Java String.equals против ==
  • Как сравнить строки в Java?

Строковые литералы войдут в String Constant Pool .

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

введите описание изображения здесь


Создание объектов по строкам:

 String str1 = new String("java5"); 

Используя строковый литерал «java5» в конструкторе, новое строковое значение сохраняется в пуле строковых констант. Используя новый оператор, в куче создается новый строковый объект с «java5» в качестве значения.

 String str2 = "java5" 

Ссылка «str2» указана на уже сохраненное значение в пуле строковых констант

 String str3 = new String(str2); 

Новый строковый объект создается в куче с тем же значением, что и ссылка на «str2»,

 String str4 = "java5"; 

Ссылка «str4» указана на уже сохраненное значение в пуле константных строк

Всего объектов: Куча – 2, Бассейн – 1

Дальнейшее чтение сообщества Oracle

Один создает строку в пуле постоянных строк

 String s = "text"; 

другой создает строку в константном пуле ( "text" ) и другую строку в обычном пространстве ( s ) кучи. Обе строки будут иметь то же значение, что и «текст».

 String s = new String("text"); 

s затем теряется (подходит для GC), если позже не используется.

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

JLS

Концепция называется «интернированием» JLS.

Соответствующий переход от JLS 7 3.10.5 :

Более того, строковый литерал всегда ссылается на тот же экземпляр classа String. Это связано с тем, что строковые литералы, или, в более общем смысле, строки, которые являются значениями константных выражений (§15.28), «интернированы», чтобы обмениваться уникальными экземплярами, используя метод String.intern.

Пример 3.10.5-1. Строковые литералы

Программа, состоящая из блока компиляции (§7.3):

 package testPackage; class Test { public static void main(String[] args) { String hello = "Hello", lo = "lo"; System.out.print((hello == "Hello") + " "); System.out.print((Other.hello == hello) + " "); System.out.print((other.Other.hello == hello) + " "); System.out.print((hello == ("Hel"+"lo")) + " "); System.out.print((hello == ("Hel"+lo)) + " "); System.out.println(hello == ("Hel"+lo).intern()); } } class Other { static String hello = "Hello"; } 

и блок компиляции:

 package other; public class Other { public static String hello = "Hello"; } 

производит выход:

 true true true true false true 

JVMs

JVMS 7 5.1 говорит :

Строковый литерал является ссылкой на экземпляр classа String и выводится из структуры CONSTANT_String_info (§4.4.3) в двоичном представлении classа или интерфейса. Структура CONSTANT_String_info дает последовательность кодовых точек Unicode, составляющих строковый литерал.

Язык программирования Java требует, чтобы идентичные строковые литералы (то есть литералы, которые содержат одну и ту же последовательность кодовых точек) должны относиться к одному экземпляру classа String (JLS §3.10.5). Кроме того, если метод String.intern вызывается в любой строке, результатом является ссылка на тот же экземпляр classа, который будет возвращен, если эта строка появилась как литерал. Таким образом, следующее выражение должно иметь значение true:

 ("a" + "b" + "c").intern() == "abc" 

Чтобы получить строковый литерал, виртуальная машина Java проверяет последовательность кодовых точек, заданную структурой CONSTANT_String_info.

  • Если метод String.intern ранее был вызван в экземпляр classа String, содержащий последовательность кодовых точек Unicode, идентичную последовательности, заданной структурой CONSTANT_String_info, тогда результат строкового литерала является ссылкой на тот же экземпляр classа String.

  • В противном случае создается новый экземпляр classа String, содержащий последовательность кодовых точек Unicode, заданную структурой CONSTANT_String_info; ссылка на этот экземпляр classа является результатом строкового литерала. Наконец, вызывается метод intern нового экземпляра String.

Bytecode

Поучительно также взглянуть на реализацию байт-кода на OpenJDK 7.

Если мы декомпилируем:

 public class StringPool { public static void main(String[] args) { String a = "abc"; String b = "abc"; String c = new String("abc"); System.out.println(a); System.out.println(b); System.out.println(a == c); } } 

у нас есть постоянный пул:

 #2 = String #32 // abc [...] #32 = Utf8 abc 

и main :

  0: ldc #2 // String abc 2: astore_1 3: ldc #2 // String abc 5: astore_2 6: new #3 // class java/lang/String 9: dup 10: ldc #2 // String abc 12: invokespecial #4 // Method java/lang/String."":(Ljava/lang/String;)V 15: astore_3 16: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 19: aload_1 20: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 23: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 26: aload_2 27: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 30: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 33: aload_1 34: aload_3 35: if_acmpne 42 38: iconst_1 39: goto 43 42: iconst_0 43: invokevirtual #7 // Method java/io/PrintStream.println:(Z)V 

Обратите внимание, как:

  • 0 и 3 : ldc #2 и та же ldc #2 (литералы)
  • 12 : создается новый экземпляр строки (с аргументом #2 качестве аргумента)
  • 35 : a и c сравниваются как обычные объекты с if_acmpne

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

  • у него есть специальная структура CONSTANT_String_info , в отличие от обычных объектов (например, new String )
  • структура указывает на структуру CONSTANT_Utf8_info , содержащую данные. Это единственные необходимые данные для представления строки.

и приведенная выше цитата JVMS, похоже, говорит, что всякий раз, когда указатель Utf8 одинаковый, то идентичные экземпляры загружаются ldc .

Я сделал аналогичные тесты для полей и:

  • static final String s = "abc" указывает на таблицу констант через атрибут ConstantValue
  • не конечные поля не имеют этого атрибута, но все еще могут быть инициализированы с помощью ldc

Вывод : имеется прямая поддержка байт-кода для пула строк, и представление памяти является эффективным.

Бонус: сравните это с пулом Integer , который не имеет прямой поддержки байт-кода (т. CONSTANT_String_info Аналога CONSTANT_String_info ).

Подумайте, что "bla" – волшебная фабрика, такая как Strings.createString("bla") (псевдо). На заводе есть пул всех строк, созданных таким образом.

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

Если нет, он создает внутренний объект строки внутри, сохраняет его в пуле и затем возвращает его. Таким образом, когда в следующий раз запрашивается одно и то же строковое значение, он возвращает тот же экземпляр.

Вручное создание new String("") отменяет это поведение путем обхода пула строковых литералов. Поэтому равенство должно всегда проверяться с помощью equals() которое сравнивает последовательность символов вместо равенства ссылки на объект.

Один простой способ понять разницу ниже: –

 String s ="abc"; String s1= "abc"; String s2=new String("abc"); if(s==s1){ System.out.println("s==s1 is true"); }else{ System.out.println("s==s1 is false"); } if(s==s2){ System.out.println("s==s2 is true"); }else{ System.out.println("s==s2 is false"); } 

выход

 s==s1 is true s==s2 is false 

Таким образом, новый String () всегда будет создавать новый экземпляр.

@Braj: Я думаю, вы упоминали об этом наоборот. Пожалуйста, поправьте меня, если я ошибаюсь

Создание объектов по строкам:

String str1 = new String (“java5”)

  Pool- "java5" (1 Object) Heap - str1 => "java5" (1 Object) 

Строка str2 = “java5”

  pool- str2 => "java5" (1 Object) heap - str1 => "java5" (1 Object) 

String str3 = new String (str2)

  pool- str2 => "java5" (1 Object) heap- str1 => "java5", str3 => "java5" (2 Objects) 

Строка str4 = “java5”

  pool - str2 => str4 => "java5" (1 Object) heap - str1 => "java5", str3 => "java5" (2 Objects) 

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

 String str = new String("hello") 

Он проверит, содержит ли постоянный пул строк String «hello»? Если присутствует, то он не будет добавлять запись в пул строк String. Если нет, то он добавит запись в пул строк String.

Объект будет создан в области памяти кучи, а ссылочные точки – объекту, созданному в ячейке памяти кучи.

если вы хотите, чтобы ссылка str на объект точки, содержащийся в пуле констант String, нужно явно вызвать str.intern();

 String str = "world"; 

Он проверит, содержит ли постоянный пул строк String «hello»? Если присутствует, то он не будет добавлять запись в пул строк String. Если нет, то он добавит запись в пул строк String.

В приведенном выше примере str ссылается на String "world" присутствующий в Constant pool.

  • Как использовать регулярное выражение в методе String.contains () в Java
  • Проверьте, содержит ли строка только буквы
  • Как интерполировать переменные в строках в JavaScript, без конкатенации?
  • Как можно объединить две строки?
  • Самый элегантный способ повторения слов строки
  • Преобразование строки Hex в ASCII в Java
  • Как удалить последний символ из строки?
  • Удаление дубликатов из строки в Java
  • Чтение файла по строке в C #
  • Простой способ удалить несколько пробелов в строке?
  • Разделить строку с разделителями на C
  • Interesting Posts

    Как я могу ограничить приоритет ввода-вывода диска для процесса в Windows XP?

    Android: вертикальный ViewPager

    Можно ли обновить Windows XP после апреля 2014 года?

    Элемент управления Dropdownlist с помощью s для asp.net (webforms)?

    java.lang.RuntimeException: сбой takePicture

    Удалить «Файл данных Outlook»

    Какой значок Dropbox предназначен для имени идентификатора значка Overlay?

    Перекрестно проверять адреса электронной почты и удалять всю строку дубликатов?

    API JavaMail для iMail – java.net.SocketException: Permission denied: connect

    Использование переменных в именах свойств в LESS (динамические свойства / интерполяция свойств)

    Порядок методов расширения LINQ не влияет на производительность?

    Перегрузка и переопределение

    Mipmaps vs. drawable folders

    Может ли один исполняемый файл быть консольным и графическим приложением?

    Можно ли суммировать весь столбец без установки явных границ ячеек в Excel?

    Давайте будем гением компьютера.