分配和创建字符串实例之间有什么区别?

Sha*_*shi 8 java memory string

在一次采访问题中,采访者问我

以下陈述之间的共同点和区别是什么:

String s = "Test";

String s = new String("Test");
Run Code Online (Sandbox Code Playgroud)

内存分配有什么不同吗?

cod*_*ict 9

String s = "Test"; 
Run Code Online (Sandbox Code Playgroud)

首先会在字符串常量池中查找字符串"Test".如果发现s将被引用以找到找到的对象.如果未找到,则创建一个新的String对象,将其添加到池中,并使s引用新创建的对象.

String s = new String("Test");
Run Code Online (Sandbox Code Playgroud)

首先会创建一个新的字符串对象并使其引用它.此外,字符串"Test"的条目在字符串常量池中生成,如果它尚未存在.

因此,假设字符串"Test"不在池中,第一个声明将创建一个对象,而第二个声明将创建两个对象.


sat*_*esh 5

内存术语的不同之处在于表单的表达式: String s = "test"使用"interned"字符串以共享唯一的实例.

形式的调用: String s = "test"
与之相比是有效的 String s = new String("test")

第一个调用使用现有的常量表达式(如果有的话),第二个调用创建一个新的实例而不使用任何现有的实例.

下面的代码块演示了这个:

String test = new String("test");
String internTest = "test";
String nonInternTest = new String("test");

System.out.println(test == internTest); // prints false
System.out.println(test != nonInternTest); // prints true
System.out.println(test.equals(nonInternTest)); // prints true
Run Code Online (Sandbox Code Playgroud)

另请注意,JLS指定了行为:
每个字符串文字都是对String类实例的引用(第4.3.3节).String对象具有常量值.字符串文字 - 或者更一般地说,作为常量表达式值的字符串被"实现",以便使用String.intern方法共享唯一实例.