剖析java中的String之__拼接
剖析java中的String之__拼接
分類: java 2011-08-24 17:46 31人閱讀 評論(0) 收藏 舉報出處,?http://blog.csdn.net/izard999/article/details/6708433
網(wǎng)上剖析String的不少,關(guān)于其他的String的知識我就不累贅去說了!
本文只解釋下我在面試中遇到的String拼接的問題以及最近看到了網(wǎng)上的一道機試題跟這個有關(guān)系, 所以就想把自己對String拼接的理解分享給大家!??
去華為面試的時候, 第一筆試題就讓我費神去想了, 回來在機子上運行結(jié)果, 發(fā)現(xiàn)自己當(dāng)時答錯了, 于是就狠下心來花了點時間研究這個:
view plain答案是nullabc!
就這三行代碼, 我問了不下于50個人, 有資深的人也有新手的, 在不運行的情況下全答錯了。!? 可見現(xiàn)在學(xué)java的人有很多人都是速成的,而且這種原理級而又看似不怎么實用的東西幾乎沒什么人去研究, 但是后面說的機試如果能知道String拼接的原理的話。將很容易就解決!
很早的時候我就知道String拼接中間會產(chǎn)生StringBuilder對象(JDK1.5之前產(chǎn)生StringBuffer),但是當(dāng)時也沒有去深究內(nèi)部, 導(dǎo)致在華為筆試此題就錯了!
運行時, 兩個字符串str1, str2的拼接首先會調(diào)用 String.valueOf(obj),這個Obj為str1,而String.valueOf(Obj)中的實現(xiàn)是return obj == null ? "null" : obj.toString(), 然后產(chǎn)生StringBuilder, 調(diào)用的StringBuilder(str1)構(gòu)造方法, 把StringBuilder初始化,長度為str1.length()+16,并且調(diào)用append(str1)! 接下來調(diào)用StringBuilder.append(str2), 把第二個字符串拼接進去, 然后調(diào)用StringBuilder.toString返回結(jié)果!
所以那道題答案的由來就是StringBuilder.append("null").append("abc").toString();
大家看了我以上的分析以后, 再碰到諸如此類的面試題應(yīng)該不會再出錯了!
那么了解String拼接有什么用呢?
在做多線程的時候, 往往會用到一個同步監(jiān)視器對象去同步一個代碼塊中的代碼synchronized(Obj),?? 對同一個對象才會互斥,不是同一個對象就不會互斥!
這里有個機試題,
現(xiàn)有程序同時啟動了4個線程去調(diào)用TestDo.doSome(key, value)方法,由于TestDo.doSome(key, value)方法內(nèi)的代碼是先暫停1秒,然后再輸出以秒為單位的當(dāng)前時間值,所以,會打印出4個相同的時間值,如下所示:
??4:4:1258199615
??1:1:1258199615
??3:3:1258199615
??1:2:1258199615
??????? 請修改代碼,如果有幾個線程調(diào)用TestDo.doSome(key, value)方法時,傳遞進去的key相等(equals比較為true),則這幾個線程應(yīng)互斥排隊輸出結(jié)果,即當(dāng)有兩個線程的key都是"1"時,它們中的一個要比另外其他線程晚1秒輸出結(jié)果,如下所示:
??4:4:1258199615
??1:1:1258199615
??3:3:1258199615
??1:2:1258199616
?? 總之,當(dāng)每個線程中指定的key相等時,這些相等key的線程應(yīng)每隔一秒依次輸出時間值(要用互斥),如果key不同,則并行執(zhí)行(相互之間不互斥)。原始代碼如下:
我直接synchronized(key),不就完了么.?? 這類人肯定是新手級別的了!
上面說了,synchronized(Obj),?? 對同一個對象才會互斥,不是同一個對象就不會互斥! 大家請看下Test類中的構(gòu)造方法里面對key做了什么處理?
this.key = key + key2;
關(guān)于字符串的拼接,? 如果是兩個常量的拼接, 那么你無論拼接多少下都是同一個對象,? 這個是編譯時?編譯器自動去優(yōu)化的(想知道具體原理的自己去網(wǎng)上搜下).
view plain這段代碼輸出true沒有問題
但是一旦涉及到變量了, 我在上面標(biāo)紅加粗的運行時,??? 此時拼接字符串就會產(chǎn)生StringBuilder,? 然而拼接完返回的字符串是怎么返回的呢?
在StringBuilder.toString()中的實現(xiàn)是new String(char value[], int offset, int count), 既然是創(chuàng)建String返回的, 那么調(diào)用一次toString,就是一個不同的對象
view plain
所以在那道機試題中, 就不能直接用synchronized(key)去同步了,? 如果你完完全全很耐心的看完本文, 那么應(yīng)該知道如何用synchronized(key)同步那段代碼了!
不錯, 就是修改Test構(gòu)造方法中的 this.key = key + key2;為this.key = key;
因為字符串不涉及到拼接的時候, 只要不new, 多少都是指向同一個對象!
當(dāng)然這道多線程的題你也可以把那個key丟到集合里面去,用集合去的contains(obj)去判斷,如果集合中存在, 就取集合中的, 否則往集合中添加,但是記住一定要使用并發(fā)包下面的集合, 否則可能會拋出ConcurrentModificationException
總結(jié)
以上是生活随笔為你收集整理的剖析java中的String之__拼接的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ConcurrentLinkedQueu
- 下一篇: MFC如何使控件大小随着对话框大小自动调