这个问题在 StackOverflow 上被问过很多次,但没有一个是基于性能的。
在 Effective Java 书中给出了这一点
If
String s = new String("stringette");
occurs in a loop or in a frequently invoked method, millions of String instances can be created needlessly.The improved version is simply the following:
String s = "stringette";
This version uses a single String instance, rather than creating a new one each time it is executed.
因此,我尝试了这两种方法并发现性能显着改进:
for (int j = 0; j < 1000; j++) {
String s = new String("hello World");
}
大约需要 399 372 纳秒。
for (int j = 0; j < 1000; j++) {
String s = "hello World";
}
大约需要 23 000 纳秒。
为什么会有这么大的性能提升?内部是否发生了任何编译器优化?
最佳答案
在第一种情况下,每次迭代都会创建一个新对象,在第二种情况下,它总是同一个对象,从字符串常量池中检索。
在 Java 中,当您这样做时:
String bla = new String("xpto");
您强制创建一个新的 String 对象,这会占用一些时间和内存。
另一方面,当您这样做时:
String muchMuchFaster = "xpto"; //String literal!
String 只会在第一次被创建(一个新对象),它会被缓存在 String
常量池中,所以每次你以它的字面形式引用它时,你得到完全相同的对象,速度快得惊人。
现在您可能会问...如果代码中的两个不同点检索到相同的文字并对其进行更改,那不是必然会发生问题吗?!
不,因为在 Java 中,您可能很清楚,字符串是不可变的!因此,任何会改变 String 的操作都会返回一个新的 String,让任何其他对同一文字的引用顺其自然。
这是不可变数据结构的优点之一,但这完全是另一个问题,我会就这个主题写几页。
编辑
澄清一下,常量池不是 String 类型独有的,您可以在此处阅读更多相关信息,或者如果您通过 google 搜索 Java 常量池。
http://docs.oracle.com/javase/specs/jvms/se7/jvms7.pdf
此外,您可以做一个小测试来说明这一点:
String a = new String("xpto");
String b = new String("xpto");
String c = "xpto";
String d = "xpto";
System.out.println(a == b);
System.out.println(a == c);
System.out.println(c == d);
有了这些,你大概可以算出这些 Sysouts 的结果:
false
false
true
因为 c
和 d
是同一个对象,所以 ==
比较成立。
关于java - new String() 与文字字符串性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14757978/