深入String、StringBuilder、StringBuffer
目錄:
1.String
2.StringBuilder和StringBuffer
3.String、StringBuild、StringBuffer區(qū)別
1.String
(1)String的基本用法:
indexOf():返回指定字符的索引。 charAt():返回指定索引處的字符。 replace():字符串替換。 trim():去除字符串兩端空白。 split():分割字符串,返回一個(gè)分割后的字符串?dāng)?shù)組。 getBytes():返回字符串的 byte 類型數(shù)組。 length():返回字符串長(zhǎng)度。 toLowerCase():將字符串轉(zhuǎn)成小寫字母。 toUpperCase():將字符串轉(zhuǎn)成大寫字符。 substring():截取字符串。 equals():字符串比較。(2)String的特點(diǎn)
1.String不是基本數(shù)據(jù)類型,String 底層是一個(gè) char 類型的數(shù)組
2.使用 final 來定義 String 類,表示 String 類不能被繼承
3.String 對(duì)象創(chuàng)建之后,會(huì)在字符串常量池中進(jìn)行緩存,如果下次創(chuàng)建同樣的對(duì)象時(shí),會(huì)直接返回緩存的引用。
4.String內(nèi)容是不可變的但不代表引用不可以變,String 是只讀字符串,對(duì)它進(jìn)行任何操作,其實(shí)都是創(chuàng)建一個(gè)新的對(duì)象,再把引用指向該對(duì)象。不變模式的主要作用在于當(dāng)一個(gè)對(duì)象需要被多線程共享并頻繁訪問時(shí),可以保證數(shù)據(jù)的一致性。
前兩點(diǎn)可以通過源碼來解釋:
這個(gè)第3,4點(diǎn)怎么理解呢,看個(gè)例子
答案是:
再細(xì)品這兩句話
String 對(duì)象創(chuàng)建之后,會(huì)在字符串常量池中進(jìn)行緩存,如果下次創(chuàng)建同樣的對(duì)象時(shí),會(huì)直接返回緩存的引用
String內(nèi)容是不可變的但不代表引用不可以變,String 是只讀字符串,對(duì)它進(jìn)行任何操作,其實(shí)都是創(chuàng)建一個(gè)新的對(duì)象(博主認(rèn)為這個(gè)新的對(duì)象創(chuàng)建在堆區(qū)為啥呢看下圖),再把引用指向該對(duì)象
如果c也在方法區(qū)那么為啥創(chuàng)建的新的四個(gè)ghjk為啥沒有一個(gè)的引用和c一樣
(3)字符串常量池
String是字符串常量那么什么是字符串常量池?
字符串常量池位于堆內(nèi)存中,專門用來存儲(chǔ)字符串常量,可以提高內(nèi)存的使用率,避免開辟多塊空間存儲(chǔ)相同的字符串,在建字符串時(shí) JVM 會(huì)首先檢查字符串常量池,如果該字符串已經(jīng)存在池中,則返回它的引用,如果不存在,則實(shí)例化一個(gè)字符串放到池中,并返回其引用。
(4)兩種創(chuàng)建字符串對(duì)象相同嗎:String str="abc"與 String str=new String(“abc”)
答案當(dāng)然是不一樣,因?yàn)閮?nèi)存的分配方式不一樣。
String str="abc"的方式,java 虛擬機(jī)會(huì)將其分配到常量池中;而 String str=new String(“abc”) 則會(huì)被分到堆內(nèi)存中(當(dāng)然也沒這么簡(jiǎn)單下面會(huì)講)
(5)創(chuàng)建對(duì)象個(gè)數(shù)的問題:
String str=new String(“abc”)
其實(shí)這里有兩種情況:
第一種當(dāng)常量池沒有“abc”這個(gè)字符串的話就創(chuàng)建兩個(gè)對(duì)象
當(dāng)常量池中沒有字符串“abc”的時(shí)候那么創(chuàng)建一個(gè)對(duì)象在堆區(qū),然后再在常量區(qū)創(chuàng)建一個(gè)字符串常量“abc”
博主你怎么知道你頭大?
博主:沒錯(cuò)我就是頭大
兄弟們拿刀
博主:別別別,我好好講還不行嗎
我們都知道String本質(zhì)還是一個(gè)字符串?dāng)?shù)組那么當(dāng)我們?cè)賱?chuàng)建String b=“abc”(這里如果常量區(qū)有“abc”就把這個(gè)引用賦給b,沒有就在常量區(qū)創(chuàng)建一個(gè)“abc對(duì)象”前面說了),由源碼我們知道String本質(zhì)其實(shí)是一個(gè)value[]的字符串?dāng)?shù)組,我們比較b的value和str的value發(fā)現(xiàn)他倆地址一樣,這不就驗(yàn)證了我剛才創(chuàng)建兩個(gè)的說法了嗎
第二種當(dāng)常量池有“abc”這個(gè)字符串的時(shí)候就創(chuàng)建一個(gè)對(duì)象
和上面一樣只不過b=“abc”在str=new String之前一樣去比較兩個(gè)對(duì)象的底層數(shù)組得出創(chuàng)建一個(gè)對(duì)象
2.StringBuffer和StringBuilder
(1)
存在于java.lang.StringBuilder中,我們知道String是字符串常量,不可以改變指向的對(duì)象值,只能改變指向的對(duì)象,那么StringBuilder就不一樣了,他是一個(gè)可變的字符串序列
原來StringBuilder是個(gè)字符串的緩沖區(qū),即它是一個(gè)容器,容器中可以裝很多字符串。并且能夠?qū)ζ渲械淖址M(jìn)行各種操作,它的內(nèi)部擁有一個(gè)數(shù)組用來存放字符串內(nèi)容,進(jìn)行字符串拼接時(shí),直接在數(shù)組中加入新內(nèi)容。StringBuilder會(huì)自動(dòng)維護(hù)數(shù)組的擴(kuò)容原理如下:
(2)常用的方法:
運(yùn)行結(jié)果:
這里注意append方法返回StringBuffer對(duì)象。toString()會(huì)把一個(gè)StringBuffer對(duì)象轉(zhuǎn)換成一個(gè)String對(duì)象,一個(gè)StringBuffer對(duì)象的引用是不能等于一個(gè)String對(duì)象的
StringBuffer和StringBuilder兩個(gè)用法差不多StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中也是使用字符數(shù)組保存字符串,char[] value,這兩種對(duì)象都是可變的。
3.String、StringBuild、StringBuffer的區(qū)別
1.String中的對(duì)象是不可變的,也就可以理解為常量,線程安全。AbstractStringBuilder是StringBuilder與StringBuffer的公共父類,定義了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer對(duì)方法加了同步鎖或者對(duì)調(diào)用的方法加了同步鎖,所以是線程安全的。StringBuilder并沒有對(duì)方法進(jìn)行加同步鎖,所以是非線程安全的。
2.每次對(duì)String 類型進(jìn)行改變的時(shí)候,都會(huì)生成一個(gè)新的String對(duì)象,然后將指針指向新的String 對(duì)象。StringBuffer每次都會(huì)對(duì)StringBuffer對(duì)象本身進(jìn)行操作,而不是生成新的對(duì)象并改變對(duì)象引用。相同情況下使用StirngBuilder 相比使用StringBuffer 僅能獲得10%~15% 左右的性能提升,但卻要冒多線程不安全的風(fēng)險(xiǎn)。
3.如果要操作少量的數(shù)據(jù)用 =》 String。
單線程操作字符串緩沖區(qū) 下操作大量數(shù)據(jù) =》 StringBuilder。
多線程操作字符串緩沖區(qū) 下操作大量數(shù)據(jù) = 》StringBuffer。
總結(jié)
以上是生活随笔為你收集整理的深入String、StringBuilder、StringBuffer的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 还在傻傻分不清楚equal和==
- 下一篇: Date、DateFormat、Cale