如果我创建一个字符串对象
String s=new String("Stackoverflow");
将String对象仅在堆中创建,或者它也在String常量池中创建一个副本。
提前致谢。
答案 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);
的副本。