两者有什么区别

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
}

其他回答

一些拆卸总是很有趣的……

$ 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是Java中不同于其他编程语言的一个类。因此,对于每个类,对象的声明和初始化是

String st1 = new String();

or

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个不同的对象,并且==检查内存位置是否相等,因此得到了结果。

But:

st1.equals(st2) // false
st2.equals(st3) // true

这里.equals()方法检查内容,st1 = "", st2 = "hello"和st3 = "hello"的内容。这就是结果。

在String声明的情况下

String st = "hello";

这里调用String类的intern()方法,检查“hello”是否在实习生池中,如果不在实习生池中,则将其添加到实习生池中,如果实习生池中存在“hello”,则st将指向现有“hello”的内存。

所以在这种情况下:

String st3 = "hello";
String st4 = "hello"; 

在这里:

st3 == st4 // true

因为st3和st4指向相同的内存地址。

另外:

st3.equals(st4);  // true as usual

String字面值是Java语言的一个概念。这是一个String字面值:

"a String literal"

String对象是java.lang.String类的一个单独实例。

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

都是有效的,但有细微的区别。s1将引用一个被压缩的String对象。这意味着,字符序列“abcde”将存储在一个中心位置,无论何时再次使用相同的文字“abcde”,JVM都不会创建一个新的String对象,而是使用缓存的String的引用。

s2肯定是一个新的String对象,所以在这种情况下,我们有:

s1 == s2 // is false
s1 == s3 // is true
s1.equals(s2) // is true

字符串对象和字符串文字之间有细微的区别。

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”将 放在水池里。

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

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

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

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

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