字符串常量池中的新String("")会发生什么

时间:2014-02-07 07:38:54

标签: java string

如果我创建一个字符串对象

String s=new String("Stackoverflow");

将String对象仅在堆中创建,或者它也在String常量池中创建一个副本。

提前致谢。

5 个答案:

答案 0 :(得分:7)

如果你调用intern或使用字符串文字,你只会在常量池中得到一个字符串,据我所知。

每次调用new String(...)时,无论您调用哪个构造函数重载,都只会得到一个常规的新String对象。

在你的情况下,你也确保 是一个在常量池中包含内容"Stackoverflow"的字符串,因为你根本就是在使用字符串文字 - 但是如果它已经存在,它将不会添加另一个。所以要把它分开:

String x = "Stackoverflow"; // May or may not introduce a new string to the pool
String y = new String(x);   // Just creates a regular object

此外,调用new String(...)的结果将始终是对所有先前引用的不同引用 - 与使用字符串文字不同。例如:

String a = "Stackoverflow";
String b = "Stackoverflow";

String x = new String(a);
String y = new String(a);

System.out.println(a == b); // true due to constant pooling
System.out.println(x == y); // false; different objects

最后,字符串被添加到常量池的确切时间对我来说从来都不清楚,对我来说也不重要。我猜它可能在类加载(该类使用的所有字符串常量,立即加载)但它可能是基于每个方法。可以使用intern()找出一个特定的实现,但它对我来说从未如此重要:)

答案 1 :(得分:5)

在这种情况下,您构建一个全新的String对象,并且该对象不会在常量池中共享。请注意,为了构建您的new String()对象,您实际上已将String常量传递给它。常量池中String常量,但是您通过new创建的字符串不会指向同一个字符串,即使它们具有相同的值。

如果您执行了String s = "Stackoverflow",那么s将包含对池中实例的引用,也有一些方法可以让您在创建池之后将String添加到池中。

答案 2 :(得分:2)

新的String在堆中创建,而不是在字符串池中创建。

如果您希望新创建的String位于字符串池中,则需要intern()它;即。

String s = new String("Stackoverflow").intern();

...除了当然会返回你用!!开始的字符串文字对象

String s1 = "Stackoverflow";
String s2 = new String(s1);
String s3 = s2.intern();

System.out.println("s1 == s2 is " + (s1 == s2));
System.out.println("s2 == s3 is " + (s2 == s3));
System.out.println("s1 == s3 is " + (s1 == s3));

应该打印

s1 == s2 is false
s2 == s3 is false
s1 == s3 is true

为了迂腐,String中的s不是String表达式创建的new String("StackOverflow")intern()的作用是在字符串池中查找其目标对象。如果池中已存在与正在查找的对象equal(Object)的字符串,则 将作为结果返回。在这种情况下,我们可以保证字符串池中已经有一个对象;即String对象,表示文字的值。

答案 3 :(得分:1)

将在堆中创建常规Java对象,并且引用s类型为String。并且,String Constant Pool中将有String literal。两者都是两回事。

答案 4 :(得分:0)

我的回答是肯定的!

首先检查以下代码:

String s0 = "Stackoverflow";
String s1 = new String("Stackoverflow");
String s2 = s1.intern();

System.out.println(s0 == s1);
System.out.println(s1 == s2 );
System.out.println(s0 == s2);

//OUTPUT:
false
false
true

s0在字符串池中保存引用,而new String(String original)将始终构造一个新实例。 intern()的{​​{1}}方法将在字符串池中返回具有相同值的引用。

现在回到你的问题:

String对象是仅在堆中创建的,还是在String常量池中复制?

由于您已经编写了一个字符串常量String并将其传递给"Stackoverflow"构造函数,因此在我看来,它具有与以下内容相同的语义:

String

这意味着在评估代码时,String常量池中将有一个副本。

但是,如果使用以下代码构造String s0 = "Stackoverflow"; String s1 = new String(s0); 对象:

String

常量池中不会有String s = new String("StackoverflowSOMETHINGELSE".toCharArray(),0,13); 的副本。