В чем разница между
String str = new String("abc");
и
String str = "abc";
В чем разница между
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
В общем, вы должны использовать текстовую литературу, когда это возможно. Его легче читать, и он дает компилятору возможность оптимизировать ваш код.
Строковый литерал - это концепция языка Java. Это строковый литерал:
"a String literal"
Объект String является отдельным экземпляром класса java.lang.String.
String s1 = "abcde";
String s2 = new String("abcde");
String s3 = "abcde";
Все действительны, но имеют небольшую разницу. s1 будет ссылаться на интернированный объект String. Это означает, что символьная последовательность "abcde" будет храниться в центральном месте, и всякий раз, когда один и тот же литерал "abcde" будет использоваться снова, JVM не будет создавать новый объект String, а использовать ссылку на кешированную строку.
 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. Вы можете принудительно создать создание нового Object в куче, выполнив следующее:
String str = new String("abc");
String str2 = new String("abc");
boolean identity = str == str2;
В этом случае str и str2 являются ссылками на разные Objects, ни один из которых не был интернирован, поэтому, когда вы тестируете идентификатор Object с помощью ==, вы получите false.
С точки зрения хорошей практики кодирования: не используйте == для проверки равенства строк, вместо этого используйте .equals().
Поскольку строки неизменяемы, когда вы делаете:
String a = "xyz"
при создании строки JVM ищет в пуле строк, если уже существует строковое значение "xyz", если so 'a' будет просто ссылкой на эту строку и не будет создан новый объект String.
Но если вы скажете:
String a = new String("xyz")
вы заставляете JVM создавать новую ссылку String, даже если "xyz" находится в пуле.
Для получения дополнительной информации прочтите this.
 "abc" - буквальная строка.
В Java эти литеральные строки объединены внутри и один и тот же экземпляр String "abc" используется там, где у вас есть этот строковый литерал, объявленный в вашем коде. Таким образом, "abc" == "abc" всегда будет истинным, поскольку они оба являются одинаковыми экземплярами String.
Используя метод String.intern(), вы можете добавить любую строку, которая вам нравится, к внутренне объединенным строкам, они будут храниться в памяти до тех пор, пока java выходов.
С другой стороны, использование new String("abc") создаст новый строковый объект в памяти, который логически совпадает с литералом "abc".
"abc" == new String("abc") всегда будет ложным, так как хотя они логически равны, они относятся к разным экземплярам.
Обтекание строкового конструктора вокруг строкового литерала не имеет значения, оно просто бесполезно использует больше памяти, чем нужно.
String - это класс в Java, отличный от других языков программирования. Так как для каждого класса объявление объекта и инициализация
String st1 = new String();
или
String st2 = new String("Hello"); 
String st3 = new String("Hello");
Здесь st1, st2 и st3 - разные объекты.
То есть:
st1 == st2 // false
st1 == st3 // false
st2 == st3 // false
Поскольку st1, st2, st3 ссылаются на 3 разных объекта, а == проверяет равенство в ячейке памяти, следовательно, результат.
Но:
st1.equals(st2) // false
st2.equals(st3) // true
Здесь .equals() проверяет содержимое и содержимое st1 = "", st2 = "hello" и st3 = "hello". Следовательно, результат.
И в случае объявления String
String st = "hello";
Здесь вызывается метод intern() класса String и проверяется, находится ли "hello" в старом пуле, а если нет, он добавляется в внутренний пул, и если в общедоступном пуле есть "привет", st будет указывать на память существующего "hello".
Итак, в случае:
String st3 = "hello";
String st4 = "hello"; 
Здесь:
st3 == st4 // true
Потому что st3 и st4 указывают на тот же адрес памяти.
также:
st3.equals(st4);  // true as usual
В первом случае создается два объекта.
Во втором случае это всего лишь один.
Хотя оба пути 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
}
В дополнение к уже опубликованным ответам также см. эту отличную статью о javaranch.
Согласно Документация класса String, они эквивалентны.
Документация для String(String original) также гласит, что: если явная копия оригинала не нужна, использование этого конструктора необязательно, поскольку строки являются неизменяемыми.
Ищите другие ответы, потому что кажется, что документация Java вводит в заблуждение: (
Ниже приведены некоторые сравнения:
String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");
System.out.println(s1 == s2); //true
System.out.println(s1.equals(s2)); //true
System.out.println(s1 == s3);   //false
System.out.println(s1.equals(s3)); //true
s3 = s3.intern();
System.out.println(s1 == s3); //true
System.out.println(s1.equals(s3)); //true
Когда intern() вызывается, ссылка изменяется.
Существует тонкие различия между объектом 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" будет
размещаться в пуле.
 String s = new String("FFFF") создает 2 объекта: "FFFF" string и String объект, который указывает на строку "FFFF", поэтому он похож на указатель на указатель (ссылка на ссылку, я не увлекаюсь терминологией).
Говорят, вы никогда не должны использовать new String("FFFF")