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

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

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

String s = "Test"; String s = new String("Test"); 

内存分配有什么不同吗?

 String s = "Test"; 

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

 String s = new String("Test"); 

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

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

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

forms的调用: 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 

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

String s =“Test”; //创建一个String对象和一个引用变量在这个简单的情况下,“Test”将进入池中,s将引用它。

String s = new String(“Test”); //创建两个对象和一个引用变量在这种情况下,因为我们使用new关键字,Java将在普通(非池)内存中创建一个新的String对象,s将引用它。 此外,文字“测试”将被放置在池中。

但它们的共同之处在于它们都创建了一个新的String对象,其值为“Test”,并将其分配给引用变量s。

第一个将搜索字符串池中的字符串文字“Test”,如果它存在则s将引用它并且不会创建新的。 并且仅当“Test”文字不存在时才创建新对象。

但在第二种情况下,它将创建另一个对象,而不必担心它是否存在。

+创建一个新的String对象和创建引用之间的差异是什么,但我们告诉jvm创建一个新对象。 并创建refence意味着我们只创建我们自己的对象。