问题在于看了<practical java>的实践 31:如欲进行字符串接合,StringBuffer优于String.
其中使用new String("...")形式产生的bytecode中显示产生了两个String对象!
做了以下实验:比较Test.java和Test1.java两者之间的bytecode.
package com.my;
public class Test {
public static void main(String[] args) {
String str = new String("hello");
}
}
package com.my;
public class Test2 {
public static void main(String[] args) {
String str = "hello";
}
}
两者生成的bytecode的图示如下:
左边的bytecode中 NEW java/lang/String 创建了第一个String对象;
LDC "hello"
INVOKESPECIAL java/lang/String.<init> 调用了String的构造函数,创建了第二个String对象;
而右边只有
LDC “hello”
从两者的bytecode来看new String("...")的形式比"..."的形式的确多产生了一个String对象.
答案在<深入java虚拟机中>:
java为了效率的考虑,使用"...."的方式的字符串会在编译时直接放入到文字池中,而运行时文字池成为了常量池的一部分.使用文字池的好处在于:对于相同的字符串常量会进行合并,在文字池中只占用一个空间.
String a = "hello";
String b = "hello";
System.out.println(a==b);
由上可知:代码输出结果 true
而对于new String("....")的形式,本来"..."已经就是一个字符串对象,并存在于文字池中,而new String()会将文字池中的"...."拷贝到堆(heap)中,并把堆(heap)中对象的引用交给字符串引用变量.所以这条语句会产生两个String对象.
String c = new String("hello");
String d = new String("hello");
System.out.println(c==d);
由上可知:代码输出结果为 false,引用变量c,d分别指向的是堆(heap)中不同的字符串对象.
参考资料:
<effective java>实践31 p107
<深入java虚拟机>
[注]eclipse使用Bytecode Outline插件,以便查看java源文件的bytecode.参考:http://dev2dev.bea.com.cn/bbsdoc/20060123182.html