工作1-3年的小伙伴應(yīng)該碰到無數(shù)次的一道面試題:
“String StringBuffer StringBuilder的區(qū)別是什么”
String 我相信大家已經(jīng)不陌生了义图,開發(fā)中應(yīng)該都離不開操作字符串拄显。等等一系列的操作與存儲(chǔ)
理解String 底層原理對(duì)于項(xiàng)目優(yōu)化起著很重要的作用卵史。
首先大家都知道String 是被final 修飾的 所有屬性也都是final 修飾的,保證了基礎(chǔ)線程安全痛黎,因?yàn)槟銓?duì)他的內(nèi)部數(shù)據(jù)無法進(jìn)行修改予弧。由于不可變?cè)赾opy數(shù)據(jù)的時(shí)候不需要額外的復(fù)制數(shù)據(jù),String的不可變?cè)O(shè)計(jì)也就是說在拼接湖饱、截?cái)嗟倪^程當(dāng)中掖蛤,都會(huì)產(chǎn)生新的String對(duì)象
JAVA 在避免過多String 對(duì)象產(chǎn)生過多的時(shí)候,引入了字符串常量池井厌。運(yùn)行機(jī)制是:在生成String 對(duì)象的時(shí)候會(huì)去找常量池里面是否有相同字符串蚓庭,如果有則把池子內(nèi)的對(duì)象引用拿出來,如果沒有那么會(huì)生成新的對(duì)象仅仆。以上說法只存在于直接給String 賦值的時(shí)候器赞,那么使用new String() 則不會(huì)去判斷池中是否會(huì)存在,則直接在堆和棧中生成新的引用和對(duì)象墓拜。
String a = "abc"
String b = new String("abc");
常量池的設(shè)計(jì) 可以節(jié)省同一字符串出現(xiàn)多次節(jié)省內(nèi)存空間港柜。
在項(xiàng)目過程中盡量的避免使用String與String的拼接,垃圾回收將會(huì)消費(fèi)大量的時(shí)間與內(nèi)存
接下來說到StringBuffer和StringBuilder
其實(shí)StringBuffer和StringBuilder 沒有本質(zhì)的區(qū)別咳榜,并且共同繼承AbstractStringBuilder類
并且底層存儲(chǔ)和String一樣夏醉,都是一個(gè)char數(shù)組,但是不同的是他們的內(nèi)容是可變的涌韩。
而它們的默認(rèn)大小是16(JDK8)如果在字符串長度大于16的時(shí)候那么會(huì)進(jìn)行擴(kuò)容畔柔。
如果在開發(fā)當(dāng)中能預(yù)估大小那么可以先預(yù)設(shè)char數(shù)組的長度,減少擴(kuò)容的開銷
大家可以去看源碼贸辈,StringBuffer和StringBuilder 在方法和屬性幾乎一致释树,StringBuffer 所有方法都用到了synchronized修飾肠槽,多線程的情況下能保證線程安全問題擎淤。同時(shí)也體現(xiàn)StringBuffer的性能遠(yuǎn)低于StringBuilder
在單線程環(huán)境當(dāng)中建議是使用StringBuilder減少同步鎖的開銷