String里不能不说的秘密

写这个题目有点大了,还请各位看官见谅。

谈不上总结,只是写写看了一些相关文章后我理解的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的某些个细节的理解上你还有所疏漏。

字符串本身会占用很大空间,而且Javafinal关键字定义了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";生成的字节码你会发现

 

 

 

JVMnew一个StringBuilder完成拼接字符串的操作所以exam == ex +  "am";的返回时隔false,每当遇上一个“+”就会重复这个操作(两个操作数都不是常量时),相对于直接用StringBufferStringBuilder节省了很多创建和销毁的开销。(有兴趣的可以写一个用了StringBuffer的例子然后反编译一下看看)

 

记住

啰嗦了那么多其实就想说下面3句话。(即是你上面的没怎么看懂没关系,记住下面的话)

     尽量避免用 new String() 来创建字符串对象。

     比较两个字符串对象是调用equals()方法,最好是把常量写在前面避免空指针的异常。

     拼接字符串时合理的运用“+” StringBuffer StringBuilder(如果不清楚还是别用“+”)

答案

Exam1true  false  false

Exam2true  false

参考资料

http://blog.csdn.net/icecityman/archive/2008/12/27/3616219.aspx

http://www.javaranch.com/journal/200408/Journal200408.jsp#a1

 

文中如有不对的地方敬请批评指正。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值