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