java - new String() 与文字字符串性能

标签 java string

这个问题在 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

因为 cd 是同一个对象,所以 == 比较成立。

关于java - new String() 与文字字符串性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14757978/

相关文章:

java - 在 JSP 的 java 脚本中操作和存储 Java hashmap( map 的 map )以便稍后在组合菜单中使用

java - 如何在多个 testng 类之间保留 Appium session

java - swt 中新窗口中的不确定进度条

android - 将本地 HTML 文件(从 Assets )加载到字符串

python - 在 Pandas 中将列转换为字符串

java - 如何在spring mvc项目中导入StreamingResponseBody?

java - 正则表达式捕获句子中常量之前的单词

c - 在目标包含源的地方使用 strncpy()

c# - 创建空数组并添加值导致 "Array index is out of range"

java - CodenameOne 如何检查字符串是否包含子字符串