Этот вопрос уже имеет ответ здесь:
Между чем различие
String str = new String("abc");
и
String str = "abc";
Когда вы используете строковый литерал, строка может быть интернирована , но когда вы используете 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
В общем, вы должны использовать нотацию строкового литерала, когда это возможно. Его легче читать, и он дает компилятору возможность оптимизировать ваш код.
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
Подробный ответ доступен здесь , поэтому я дам вам короткий.
Когда вы делаете это:
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 ()
.
«abc»
- это буквальная строка.
В Java эти строковые литералы объединяются в пул, и один и тот же экземпляр String для "abc"
используется везде, где когда-либо этот строковый литерал объявлен в вашем коде. Таким образом, "abc" == "abc"
всегда будет истинным, поскольку они оба являются одним и тем же экземпляром String.
Используя метод String.intern ()
, вы можете добавить любую строку, которая вам нравится, к строкам внутреннего пула, они будут храниться в памяти до выхода из java.
С другой стороны, использование new String («abc»)
создаст новый строковый объект в памяти, который логически совпадает с литералом «abc»
.
"abc" == new String ("abc")
всегда будет ложным, поскольку, хотя они логически равны, они относятся к разным экземплярам.
Обертка конструктора String вокруг строкового литерала не имеет значения, просто он без нужды использует больше памяти, чем нужно.
Поскольку строки неизменяемы, когда вы:
String a = "xyz"
при создании строки, JVM ищет в пуле строк, если строковое значение уже существует «xyz»
, если да 'a'
будет просто ссылкой на эту строку, и новый объект String не будет создан.
Но если вы скажете:
String a = new String("xyz")
вы заставите JVM создать новую ссылку String
, даже если «xyz»
находится в ее пуле.
Для получения дополнительной информации прочтите this .
В первом случае создаются два объекта.
Во втором случае - только один.
Хотя в обоих случаях str
ссылается на "abc"
.
Некоторые разборки всегда интересны...
$ 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
}
Согласно документации класса String они эквивалентны.
В документации для String (String original)
также говорится, что: Если не требуется явная копия оригинала, использование этого конструктора не требуется, поскольку строки неизменяемы.
Поищите другие ответы, поскольку кажется, что документация по Java вводит в заблуждение: (
В дополнение к уже опубликованным ответам, также посмотрите эту отличную статью о javaranch.
String s = new String ("FFFF")
создает 2 объекта: «FFFF»
строку и String
объект, которые указывают на «FFFF»
строка, поэтому она похожа на указатель на указатель (ссылка на ссылку, терминология меня не интересует).
Говорят, вы никогда не должны использовать новую строку ("FFFF")
Между объектом 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 " будет
быть помещенным в бассейн.