Различие между строковым литералом объектов и строковым литералом [дубликат]

Этот вопрос уже имеет ответ здесь:

Между чем различие

String str = new String("abc");

и

String str = "abc";
239
задан Burhan Khalid 24 December 2012 в 19:40
поделиться

11 ответов

Когда вы используете строковый литерал, строка может быть интернирована , но когда вы используете new String ("... ") вы получаете новый строковый объект.

В этом примере оба строковых литерала ссылаются на один и тот же объект:

String a = "abc"; 
String b = "abc";
System.out.println(a == b);  // true

Здесь создаются 2 разных объекта, и у них разные ссылки:

String c = new String("abc");
String d = new String("abc");
System.out.println(c == d);  // false

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

203
ответ дан 23 November 2019 в 03:21
поделиться

A Строковый литерал - это концепция языка Java. Это строковый литерал:

"a String literal"

Объект String является отдельным экземпляром класса java.lang.String .

String s1 = "abcde";
String s2 = new String("abcde");
String s3 = "abcde";

Все верны, но с небольшими отличиями. s1 будет ссылаться на интернированный объект String. Это означает, что последовательность символов «abcde» будет храниться в центральном месте, и всякий раз, когда тот же литерал «abcde» используется снова, JVM не будет создавать новую строку объект, но используйте ссылку на кэшированную строку.

s2 гарантированно является новым объектом String , поэтому в этом случае мы имеем:

s1 == s2 // is false
s1 == s3 // is true
s1.equals(s2) // is true
86
ответ дан 23 November 2019 в 03:21
поделиться

Подробный ответ доступен здесь , поэтому я дам вам короткий.

Когда вы делаете это:

String str = "abc";

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

Дан следующий код:

String str = "abc";
String str2 = "abc";
boolean identity = str == str2;

Когда вы проверяете идентичность объекта, выполняя == (вы буквально спрашиваете:указывают ли эти две ссылки на один и тот же объект?), вы получите true .

Однако вам не нужны от до intern () Strings . Вы можете принудительно создать новый объект в куче, выполнив следующие действия:

String str = new String("abc");
String str2 = new String("abc");
boolean identity = str == str2;

В этом случае str и str2 являются ссылками на разные ] Объекты , ни один из которых не был интернирован , поэтому при проверке идентичности объекта с помощью == вы получите false .

С точки зрения хорошей практики кодирования: не используйте == для проверки равенства строк, вместо этого используйте .equals () .

41
ответ дан 23 November 2019 в 03:21
поделиться

«abc» - это буквальная строка.

В Java эти строковые литералы объединяются в пул, и один и тот же экземпляр String для "abc" используется везде, где когда-либо этот строковый литерал объявлен в вашем коде. Таким образом, "abc" == "abc" всегда будет истинным, поскольку они оба являются одним и тем же экземпляром String.

Используя метод String.intern () , вы можете добавить любую строку, которая вам нравится, к строкам внутреннего пула, они будут храниться в памяти до выхода из java.

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

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

17
ответ дан 23 November 2019 в 03:21
поделиться

Поскольку строки неизменяемы, когда вы:

String a = "xyz"

при создании строки, JVM ищет в пуле строк, если строковое значение уже существует «xyz» , если да 'a' будет просто ссылкой на эту строку, и новый объект String не будет создан.

Но если вы скажете:

String a = new String("xyz")

вы заставите JVM создать новую ссылку String , даже если «xyz» находится в ее пуле.

Для получения дополнительной информации прочтите this .

36
ответ дан 23 November 2019 в 03:21
поделиться

В первом случае создаются два объекта.

Во втором случае - только один.

Хотя в обоих случаях str ссылается на "abc".

6
ответ дан 23 November 2019 в 03:21
поделиться

Некоторые разборки всегда интересны...

$ cat Test.java 
public class Test {
    public static void main(String... args) {
        String abc = "abc";
        String def = new String("def");
    }
}

$ javap -c -v Test
Compiled from "Test.java"
public class Test extends java.lang.Object
  SourceFile: "Test.java"
  minor version: 0
  major version: 50
  Constant pool:
const #1 = Method  #7.#16;  //  java/lang/Object."<init>":()V
const #2 = String  #17;     //  abc
const #3 = class   #18;     //  java/lang/String
const #4 = String  #19;     //  def
const #5 = Method  #3.#20;  //  java/lang/String."<init>":(Ljava/lang/String;)V
const #6 = class   #21;     //  Test
const #7 = class   #22;     //  java/lang/Object
const #8 = Asciz   <init>;
...

{
public Test(); ...    

public static void main(java.lang.String[]);
  Code:
   Stack=3, Locals=3, Args_size=1
    0:    ldc #2;           // Load string constant "abc"
    2:    astore_1          // Store top of stack onto local variable 1
    3:    new #3;           // class java/lang/String
    6:    dup               // duplicate top of stack
    7:    ldc #4;           // Load string constant "def"
    9:    invokespecial #5; // Invoke constructor
   12:    astore_2          // Store top of stack onto local variable 2
   13:    return
}
5
ответ дан 23 November 2019 в 03:21
поделиться

Согласно документации класса String они эквивалентны.

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

Поищите другие ответы, поскольку кажется, что документация по Java вводит в заблуждение: (

3
ответ дан 23 November 2019 в 03:21
поделиться

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

5
ответ дан 23 November 2019 в 03:21
поделиться

String s = new String ("FFFF") создает 2 объекта: «FFFF» строку и String объект, которые указывают на «FFFF» строка, поэтому она похожа на указатель на указатель (ссылка на ссылку, терминология меня не интересует).

Говорят, вы никогда не должны использовать новую строку ("FFFF")

0
ответ дан 23 November 2019 в 03:21
поделиться

Между объектом String и строковым литералом есть тонкие различия.

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

В этом простом случае « abc » войдет в пул, а s будет ссылаться на него.

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

В этом случае, поскольку мы использовали ключевое слово new , Java создаст новый объект String в обычной (не пул) памяти, и s будут ссылаться на нее. Кроме того, буквальный " abc " будет быть помещенным в бассейн.

1
ответ дан 23 November 2019 в 03:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: