今天就跟大家聊聊有關(guān)String、StringBuffer和StringBuilder的區(qū)別是什么,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
公司主營業(yè)務(wù):網(wǎng)站建設(shè)、成都網(wǎng)站制作、移動網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)推出臨城免費(fèi)做網(wǎng)站回饋大家。
String是Java中基礎(chǔ)且重要的類,并且String也是Immutable類的典型實(shí)現(xiàn),被聲明為final class,除了hash這個(gè)屬性其它屬性都聲明為final,因?yàn)樗牟豢勺冃?,所以例如拼接字符串時(shí)候會產(chǎn)生很多無用的中間對象,如果頻繁的進(jìn)行這樣的操作對性能有所影響。
StringBuffer就是為了解決大量拼接字符串時(shí)產(chǎn)生很多中間對象問題而提供的一個(gè)類,提供append和add方法,可以將字符串添加到已有序列的末尾或指定位置,它的本質(zhì)是一個(gè)線程安全的可修改的字符序列,把所有修改數(shù)據(jù)的方法都加上了synchronized。但是保證了線程安全是需要性能的代價(jià)的。
在很多情況下我們的字符串拼接操作不需要線程安全,這時(shí)候StringBuilder登場了,StringBuilder是JDK1.5發(fā)布的,它和StringBuffer本質(zhì)上沒什么區(qū)別,就是去掉了保證線程安全的那部分,減少了開銷。
StringBuffer 和 StringBuilder 二者都繼承了 AbstractStringBuilder ,底層都是利用可修改的char數(shù)組(JDK 9 以后是 byte數(shù)組)。
所以如果我們有大量的字符串拼接,如果能預(yù)知大小的話最好在new StringBuffer 或者StringBuilder 的時(shí)候設(shè)置好capacity,避免多次擴(kuò)容的開銷。擴(kuò)容要拋棄原有數(shù)組,還要進(jìn)行數(shù)組拷貝創(chuàng)建新的數(shù)組。
我們平日開發(fā)通常情況下少量的字符串拼接其實(shí)沒太必要擔(dān)心,例如
String str = "aa"+"bb"+"cc";
像這種沒有變量的字符串,編譯階段就直接合成"aabbcc"了,然后看字符串常量池(下面會說到常量池)里有沒有,有也直接引用,沒有就在常量池中生成,返回引用。
如果是帶變量的,其實(shí)影響也不大,JVM會幫我們優(yōu)化了。(以下運(yùn)行JDK版本為1.8)
看看反編譯結(jié)果,String拼接用的是StringBuilder.append。
是不是好像覺得那不平時(shí)不需要用StringBuilder 啊,用String就好了啊,都幫我們優(yōu)化了?
不是的來看這個(gè)情況
看看反編譯結(jié)果,new了很多次StringBuilder
也就是說會如果有大量的字符串拼接new好多StringBuilder對象,所以頻繁的字符串操作還是得用StringBuilder!
再說說字符串常量池
看看我們的代碼,你會發(fā)現(xiàn)String是真的頻繁得使用到,Java為了避免在一個(gè)系統(tǒng)中產(chǎn)生大量的String對象,引入了字符串常量池。
創(chuàng)建一個(gè)字符串時(shí),首先會檢查池中是否有值相同的字符串對象,如果有就直接返回引用,不會創(chuàng)建字符串對象;如果沒有則新建字符串對象,返回對象引用,并且將新創(chuàng)建的對象放入池中。但是,通過new方法創(chuàng)建的String對象是不檢查字符串常量池的,而是直接在堆中創(chuàng)建新對象,也不會把對象放入池中。上述原則只適用于直接給String對象引用賦值的情況。
String str1 = new String("a"); //不檢查字符串常量池的String str2 = "bb"; //檢查字符串常量池的
String還提供了intern()方法。調(diào)用該方法時(shí),如果字符串常量池中包括了一個(gè)等于此String對象的字符串(由equals方法確定),則返回池中的字符串的引用。否則,將此String對象添加到池中,并且返回此池中對象的引用。
在JDK6中,不推薦大量使用intern方法,因?yàn)檫@個(gè)版本字符串緩存在永久代中,這個(gè)空間是有限了,除了FullGC之外不會被清楚,所以大量的緩存在這容易OutOfMemoryError。
看完上述內(nèi)容,你們對String、StringBuffer和StringBuilder的區(qū)別是什么有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。