两者有什么区别

String str = new String("abc");

and

String 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
}

其他回答

"abc"是一个字面值的字符串。

在Java中,这些字面值字符串是内部池,并且在代码中声明该字符串字面值的地方使用“abc”的相同String实例。因此"abc" == "abc"将始终为真,因为它们都是相同的String实例。

使用string .intern()方法,您可以向内部池字符串中添加任何您喜欢的字符串,这些字符串将保存在内存中,直到java退出。

另一方面,使用new String("abc")将在内存中创建一个新的字符串对象,它在逻辑上与"abc"字面量相同。 "abc" == new String("abc")将始终为false,因为尽管它们在逻辑上相等,但它们指的是不同的实例。

将String构造函数包装在字符串文字周围是没有价值的,它只是不必要地使用比它需要的更多内存。

由于字符串是不可变的,当你这样做时:

String a = "xyz"

在创建字符串时,JVM在字符串池中搜索是否已经存在一个字符串值“xyz”,如果存在,'a'将只是该字符串的引用,并且不会创建新的string对象。

但如果你说:

String a = new String("xyz")

强制JVM创建一个新的String引用,即使"xyz"在它的池中。

要了解更多信息,请阅读这篇文章。

根据String类文档,它们是等价的。

String(String original)的文档还说:除非需要original的显式副本,否则使用此构造函数是不必要的,因为String是不可变的。

寻找其他的回答,因为Java文档似乎是误导性的:(

长一点的答案在这里,所以我给你一个短一点的。

当你这样做的时候:

String str = "abc";

你在String上调用intern()方法。该方法引用String对象的内部池。如果调用intern()的String已经在池中,则将该String的引用赋值给str。如果没有,则将新String放入池中,并将其引用赋值给str。

给定以下代码:

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

当你通过==来检查对象的同一性(你实际上是在问:这两个引用是否指向同一个对象?),你得到true。

但是,您不需要使用intern()字符串。你可以这样强制创建一个堆上的新对象:

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

在本例中,str和str2是对不同对象的引用,它们都没有被合并,因此当您使用==测试对象标识时,将得到false。

在良好的编码实践方面:不要使用==来检查String是否相等,而是使用.equals()来代替。

当你使用字符串字面值时,字符串可以被合并,但当你使用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

一般来说,应该尽可能使用字符串文字表示法。它更容易阅读,并给编译器一个机会来优化你的代码。