## 复习总结String、StringBuffer和StringBuilder的底层原理及区别
两个小练习
图片代码说明:java的"常量"优化机制
图片说明:s2先去常量池中找该字符串,发现没有则创建该字符串对象并在常量池中注册,返回该字符串对象的引用,因此s2记录的为常量池中的地址值;而s3为s1和"c"的拼接,jvm创建StringBuilder对象(该对象在堆内存中)使用append方法拼接字符串,拼接好后使用StringBuilder的toString()方法返回字符串(toString方法返回值为new Stirng()对象,),因此s3==s2为false,二者的地址值不同。
首先是String:
1.当使用引号引起来的直接字符串时(下面以“abc”为例),首先会去字符串常量池去找有没有该字符串的引用,如果没有则去堆中创建“abc”字符串对象(地址为0x0001),去常量池中注册该地址的引用,并将字符串对象(其实是地址值)返回给一开始的变量引用。如果常量池中有“abc”则直接使用。
2.new对象时,不会再去常量池找,直接在堆中创建对象使用,即使常量池没有“abc”也不会主动去常量池注册。
3.在字符串拼接时,jvm创建一个StringBuilder对象,使用append方法拼接,拼接好后再由StringBuilder的toString方法(该方法返回的是new的对象)获得拼接好后的字符串对象如“abcd”(=s1+“d”),同理该过程也不会主动去字符串常量池注册。String中的intern()方法。调用该方法时,同样先会去字符串常量池中查看是否有该字符串对象(由equals方法确定),如果有,则直接返回常量池中该字符串的引用。若池中没有,则将该字符串对象注册(添加)到常量池中,返回该对象的引用。
总结:只要是new的对象,都不会去常量池寻找,也不会去常量池注册;直接赋值的字符串或调用intern()方法的,会先去常量池寻找,有则直接使用,没有则创建并添加到常量池,返回引用。
String和StringBuffer,StringBuilder的区别
首先StringBuffer,StringBuilder的区别,二者底层都是字符数组,前者的方法中,大多使用sychonized修饰,是线程同步的,而后者没有。因此在使用多线程时,使用前者,不会出现线程安全问题。而单线程时可使用后者,效率更高。
其次是String和StringBuilder的区别了,前者底层为final修饰的字符数组,只能赋值一次。例如在大量字符串拼接过程中,前者每一次拼接 会创建两个stringbuilder用来拼接;而后者则只在一开始创建一个stringbuilder,拼接只用append方法不断往原缓冲区添加即可。
因此,大量字符串拼接时StingBuilder效率更高,但只有个别字符串拼接时,还是使用String更好。