写这个题目有点大了,还请各位看官见谅。
谈不上总结,只是写写看了一些相关文章后我理解的String
在听我唠叨之前先来做两个小的测验
Exam1:
String s1 = "exam";
String s2 = "exam";
String s3 = new String("exam");
String s4 = new String("exam");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s3 == s4);
Exam2:
String ex = "ex";
String am = "am";
String exam = "exam";
System.out.println(exam == "ex" + "am");
System.out.println(exam == ex + "am");
(建议拿出纸笔记录下你预想的答案然后再借助IDE进行验证,答案我留在文章末尾处)
如果console 输出的结果和你预测的结果一样,那接下来的内容你可以绕过,如果不小心错了一点点,亦或是想挑挑我文章的毛病的话continue。
String在字符串的处理上给了我们带来了很大的便利,然而通过上面的测试你会发现对于String的某些个细节的理解上你还有所疏漏。
字符串本身会占用很大空间,而且Java用final关键字定义了String类,基于这两点的考虑JVM做了一些优化,即在堆上划分了一块区域存储字符串,这块区域就是pool of literal string (文字池)。
String s1 = "exam";
JVM会先去String Pool(就是上文提到的文字池以下都用这个简称)中查找是否存在“exam” 这个字符串,如果不存在则在String Pool中创建并且返回这个字符串的引用放到s1中保存,如果存在直接返回池中的那个字符串的引用放到s1中保存。
这就是为什么s1 == s2 的结果是true。
String s3 = new String("exam");
JVM也会先去String Pool里查找是否存在字符串"exam",不存在则在String Pool中创建该字符串,因为有关键字new的存在JVM还会在堆上创建一个"exam",然后返回堆上的那个引用放到s3中保存。换句话说就是在String Pool里没有"exam"的情况下执行String s3 = new String("exam"); 会创建两个对象,一个在String Pool里,一个在堆上。(前面也说了String Pool是堆上划分出来的一块区域所以这里的堆只是相对String Pool而言)
在String类中提供了一个方法 intern() 可以帮助你拿到一个字符串在String Pool 对应的那个字符串引用。(我的描述不是很清楚,建议去看API),结合这个例子s1 == s3.intern();的返回是一个true。
为了帮助理解,我画了下面的示意图。
接下来再看Exam2。相信在进行字符串的拼接时你会很自然的选用Java提供的StringBuffer或者StringBuilder,为什么不用 “+”,可以少敲很多字符呢?通过下面对Exam2的分析你会很庆幸你的选择。
exam == "ex" + "am"; 在反编译(用javap命令)生成的字节码是你会发现和exam == "exam";等价。理解了Exam1很容易知道这个表达式返回的是一个true。在编译的时候如果“+”两边的都是字面常量会自动将其拼接在一起。如果两个操作数种出现了变量结果会是怎样?同样去反编译exam == ex + "am";生成的字节码你会发现
JVM会new一个StringBuilder完成拼接字符串的操作所以exam == ex + "am";的返回时隔false,每当遇上一个“+”就会重复这个操作(两个操作数都不是常量时),相对于直接用StringBuffer或StringBuilder节省了很多创建和销毁的开销。(有兴趣的可以写一个用了StringBuffer的例子然后反编译一下看看)。
记住
啰嗦了那么多其实就想说下面3句话。(即是你上面的没怎么看懂没关系,记住下面的话)
① 尽量避免用 new String() 来创建字符串对象。
② 比较两个字符串对象是调用equals()方法,最好是把常量写在前面避免空指针的异常。
③ 拼接字符串时合理的运用“+” 和 StringBuffer或 StringBuilder。(如果不清楚还是别用“+”)
答案:
Exam1:true false false
Exam2:true false
参考资料
http://blog.csdn.net/icecityman/archive/2008/12/27/3616219.aspx
http://www.javaranch.com/journal/200408/Journal200408.jsp#a1
文中如有不对的地方敬请批评指正。