久久亚洲成a人片熟女精品色一区二区三区|国产精品视频第一精品视频|av天堂热无码手机版|亚洲?v无码久久无遮挡|国产精品偷伦视频免费观看国产|麻豆国产自产精品丰满熟妇|av无码av不卡一区二区|久久亚洲精品中文字

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

String、StringBuilder、StringBuffer:Java字符串拼接原理與選型指南

String、StringBuilder、StringBuffer:Java字符串拼接原理與選型指南 1. 引言三兄弟的江湖不只是面試題做Java開發(fā)這么多年我沒見過哪個(gè)面試候選人在第一輪不被問到String的。String、StringBuilder、StringBuffer這三者之間的關(guān)系幾乎成了Java面試的“入門考勤卡”。但說實(shí)話很多工作了兩年三年的開發(fā)者對(duì)這三者的理解依然停留在“String是不可變的StringBuilder是線程不安全的但是快StringBuffer是線程安全的但是慢”這個(gè)背課文層面。真到了線上優(yōu)化字符串拼接、排查內(nèi)存問題、處理日志輸出的時(shí)候還是會(huì)踩坑。這篇文章我想換個(gè)角度不按教科書順序講而是從實(shí)際開發(fā)中的“為什么需要三套方案”來切入String這套不可變?cè)O(shè)計(jì)到底換來了什么StringBuilder為什么能快StringBuffer的“線程安全”到底是什么層面的安全以及日常寫代碼時(shí)到底該怎么選。順便把JDK底層實(shí)現(xiàn)、編譯期優(yōu)化、JVM內(nèi)存細(xì)節(jié)都串進(jìn)來盡量做到既有深度又能直接落地。不管你是準(zhǔn)備面試的Java工程師還是想把手上的老項(xiàng)目里那段循環(huán)拼接字符串的爛代碼優(yōu)化一下這篇文章都應(yīng)該能幫上忙。哪怕你只是路過想知道為什么new String(a) new String(b)在循環(huán)里能慢到讓人崩潰也可以看完再走。2. 為什么Java需要三套字符串方案歷史包袱還是精細(xì)分工很多人有個(gè)誤解覺得StringBuffer是老祖宗StringBuilder是后來為了性能加的新人String是最早的元老。這個(gè)理解方向大體對(duì)但少了一層關(guān)鍵邏輯這三個(gè)類并不是同一維度上的“替代關(guān)系”而是不同需求場(chǎng)景下的精細(xì)分工。理解不了這層很難真正用好它們。2.1 字符串的本質(zhì)不可變的基礎(chǔ)設(shè)施先看String為什么不可變。Java設(shè)計(jì)者把String設(shè)計(jì)成final類底層用char[]數(shù)組JDK8之前或byte[]數(shù)組JDK9之后存儲(chǔ)一旦創(chuàng)建內(nèi)容就鎖死了。這個(gè)決策在當(dāng)年是很有遠(yuǎn)見的因?yàn)樽址荍ava世界里最基礎(chǔ)的“基礎(chǔ)設(shè)施”之一大量底層機(jī)制都依賴字符串的不可變性。舉個(gè)例子String的hashCode會(huì)被緩存因?yàn)閮?nèi)容不會(huì)變所以計(jì)算一次就能永久復(fù)用。再比如字符串常量池多個(gè)變量引用同一個(gè)字符串字面量時(shí)大家共享同一份內(nèi)存完全不用擔(dān)心某個(gè)變量“偷偷改掉”公共數(shù)據(jù)。還有作為HashMap的key、作為鎖對(duì)象雖然不推薦直接用字符串鎖但很多人確實(shí)這么干過、在網(wǎng)絡(luò)傳輸和文件IO中作為傳輸載體這些都是建立在“字符串內(nèi)容可靠、穩(wěn)定、可共享”的前提之上的??梢赃@么說String的不可變性換來了Java世界大量基礎(chǔ)機(jī)制的簡(jiǎn)單和安全。代價(jià)也很直接——每次對(duì)String做修改操作拼接、替換、截取等本質(zhì)上都是在創(chuàng)建新對(duì)象。這在少量操作時(shí)無所謂一旦進(jìn)入循環(huán)或高頻場(chǎng)景就很容易觸發(fā)GC壓力甚至拖垮性能。2.2 StringBuilder為解決“頻繁修改”而生的可變序列理解了String的不可變性代價(jià)之后StringBuilder的出現(xiàn)就很自然了——它就是專門為“頻繁修改字符串內(nèi)容”這個(gè)需求設(shè)計(jì)的。StringBuilder內(nèi)部維護(hù)一個(gè)可變的數(shù)據(jù)結(jié)構(gòu)同樣是一個(gè)字符數(shù)組新增、替換、刪除都直接在這個(gè)數(shù)組上操作不需要額外創(chuàng)建新對(duì)象。用完了可以再擴(kuò)容內(nèi)容可變完全繞開了String“一次創(chuàng)建、永久不變”的限制。很多人容易把StringBuilder理解成“快版的String”其實(shí)更準(zhǔn)確的說法是“可變字符序列”。它是為了解決性能問題而生不承擔(dān)String那些“安全、穩(wěn)定、可共享”的使命。所以它不做任何線程同步所有方法都是直接操作內(nèi)部狀態(tài)——這也決定了它在單線程環(huán)境下是三者中性能最好的。2.3 StringBuffer那張只存在于特定場(chǎng)景的安全網(wǎng)StringBuffer的歷史比StringBuilder早在JDK 1.0時(shí)代就存在了。當(dāng)時(shí)Java還沒有StringBuilder多線程編程也不像現(xiàn)在這么普及設(shè)計(jì)者為了在線程安全這個(gè)維度上兜底給StringBuffer的幾乎所有方法都加了synchronized關(guān)鍵字。后來JDK 5引入了StringBuilder把“不關(guān)心線程安全、只追求性能”的場(chǎng)景單獨(dú)剝了出去。這里面有一個(gè)非常關(guān)鍵的認(rèn)知差StringBuffer的線程安全指的是“多線程環(huán)境下對(duì)同一個(gè)實(shí)例進(jìn)行修改操作時(shí)內(nèi)部狀態(tài)不會(huì)被破壞”。它保證的是數(shù)據(jù)一致性并不是說用了StringBuffer你的程序就一定線程安全。比如多個(gè)線程往同一個(gè)StringBuffer里拼接日志最后的結(jié)果可能順序是亂的——但內(nèi)容不會(huì)出現(xiàn)“寫了一半、結(jié)構(gòu)損壞”這類問題。這個(gè)區(qū)別稍后我會(huì)專門展開。2.4 三個(gè)類的關(guān)系總結(jié)一張表看透本質(zhì)我把三個(gè)類在核心維度上的差異整理成一張表方便對(duì)照維度StringStringBuilderStringBuffer引入版本JDK 1.0JDK 5JDK 1.0可變性不可變可變可變線程安全天然安全不可變線程不安全線程安全方法級(jí)synchronized性能單線程最差頻繁創(chuàng)建對(duì)象最優(yōu)中等有鎖開銷主要用途字符串常量、少量拼接、作為不可變載體單線程高頻修改/拼接多線程共享修改、遺留代碼兼容底層結(jié)構(gòu)byte[]JDK 9或char[]JDK 8-可變的char[]/byte[]可變的char[]/byte[]這張表基本就是面試口頭答案的完整版。但面試只能問到這一層真正的功夫在下一節(jié)——為什么StringBuilder在單線程下是最優(yōu)解它內(nèi)部的擴(kuò)容機(jī)制到底是什么樣的很多性能優(yōu)化經(jīng)驗(yàn)恰恰是建立在這些底層細(xì)節(jié)上的。3. 我為什么推薦你在日常開發(fā)中無腦選StringBuilder但有一個(gè)前提先亮我的個(gè)人習(xí)慣在99%的字符串拼接場(chǎng)景里我會(huì)無腦用StringBuilder而且只在必要的時(shí)候才考慮String和StringBuffer。這個(gè)習(xí)慣聽起來無腦但背后是有數(shù)據(jù)和原理支撐的。3.1 編譯器的“”優(yōu)化看起來很美實(shí)際有坑很多人會(huì)說“我直接用str xxx不就行了編譯器會(huì)自動(dòng)轉(zhuǎn)成StringBuilder的?!边@個(gè)說法在大多數(shù)情況下是對(duì)的——javac編譯器確實(shí)會(huì)把字符串的操作轉(zhuǎn)成new StringBuilder().append()...鏈?zhǔn)秸{(diào)用。但這種優(yōu)化有兩個(gè)前提問題。第一它只在單條語句內(nèi)做優(yōu)化。如果你在一個(gè)循環(huán)體里反復(fù)執(zhí)行str s每輪循環(huán)都會(huì)生成新的StringBuilder和新的String對(duì)象中間變量的創(chuàng)建和銷毀在幾千幾萬次迭代后對(duì)GC來說是一個(gè)不小的負(fù)擔(dān)。下面的代碼就是一個(gè)很典型的反面教材String str ; for (int i 0; i 10000; i) { str i; // 每輪循環(huán)都創(chuàng)建新的StringBuilder 新的String }這段代碼在極端場(chǎng)景下能被優(yōu)化成接近O(n^2)的時(shí)間復(fù)雜度因?yàn)槊看蜸tring拼接都要先創(chuàng)建一個(gè)新StringBuilder、append當(dāng)前內(nèi)容再把整個(gè)內(nèi)容拷貝到新數(shù)組然后轉(zhuǎn)成String。隨著str越來越長(zhǎng)拷貝成本越來越大。第二編譯器優(yōu)化不等于幫你按最優(yōu)方式寫代碼。即使編譯器轉(zhuǎn)成了StringBuilder它也只是簡(jiǎn)單地把操作串起來很多場(chǎng)景能進(jìn)一步手工優(yōu)化空間——比如預(yù)先指定容量、避免中間字符串的生成。3.2 高頻繁拼接的最佳實(shí)踐預(yù)分配容量StringBuilder默認(rèn)底層數(shù)組容量是16個(gè)字符。當(dāng)append的內(nèi)容超過當(dāng)前容量時(shí)會(huì)觸發(fā)擴(kuò)容機(jī)制。擴(kuò)容的具體邏輯是新容量 舊容量 * 2 2然后把舊數(shù)組內(nèi)容拷貝到新數(shù)組。這個(gè)“拷貝舊數(shù)組”的操作在高頻拼接場(chǎng)景下就是實(shí)打?qū)嵉男阅軗p耗。我在寫日志、拼SQL、構(gòu)造報(bào)文這類場(chǎng)景時(shí)習(xí)慣先估一下最終字符串的大致長(zhǎng)度然后直接new一個(gè)帶初始容量參數(shù)的StringBuilderStringBuilder sb new StringBuilder(1024); sb.append(INSERT INTO user(id, name, age) VALUES(); // 循環(huán)append參數(shù) sb.append());這里背后有兩個(gè)好處一是減少了擴(kuò)容次數(shù)二是避免了數(shù)組拷貝的損耗。實(shí)測(cè)過在幾千行的SQL構(gòu)造場(chǎng)景里預(yù)分配容量的StringBuilder和默認(rèn)容量的StringBuilder相比能節(jié)省大概20%~30%的耗時(shí)這在日千萬級(jí)日志量的系統(tǒng)里是很可觀的。3.3 字符串改為StringBuilder的兩個(gè)小竅門除了append之外StringBuilder還有一些容易被忽略的高頻方法insert、delete、replace、reverse。注意它們都是直接修改內(nèi)部數(shù)組不會(huì)產(chǎn)生新對(duì)象。比如要對(duì)一個(gè)字符串做倒序用new StringBuilder(original).reverse().toString()比手寫循環(huán)交換數(shù)組要優(yōu)雅得多而且性能不差。一個(gè)容易被坑的點(diǎn)很多人用StringBuilder時(shí)喜歡在最后直接.toString()拿到String。這個(gè)操作本身沒問題但如果你需要的是“繼續(xù)拿著這個(gè)內(nèi)容做后續(xù)拼接”就不要急著toString——因?yàn)閠oString連接了StringBuilder和String世界一旦轉(zhuǎn)成String后續(xù)的修改又要從頭開始創(chuàng)建新對(duì)象。我見過不少同事把StringBuilder轉(zhuǎn)成String后又用String去拼接繞了一大圈。這一點(diǎn)延伸開涉及一個(gè)編碼習(xí)慣問題在使用StringBuilder的場(chǎng)景盡量保持“全程StringBuilder”直到最終輸出。中途不要反復(fù)橫跳否則你就在兩個(gè)世界里反復(fù)支付轉(zhuǎn)換成本。4. StringBuffer的“線程安全”到底保護(hù)了什么我一直覺得StringBuffer是三個(gè)里面最容易被誤解的類。面試題里它被貼了“線程安全”的標(biāo)簽實(shí)際開發(fā)里大家卻幾乎不碰它。但要真問起來很少人能把那層synchronized背后的邊界條件說清楚。4.1 方法級(jí)同步的適用范圍StringBuffer的線程安全是在**“多個(gè)線程同時(shí)調(diào)用同一個(gè)StringBuffer實(shí)例的拼接方法”這個(gè)前提下成立的。它的append、insert、replace等修改方法都加了synchronized執(zhí)行時(shí)會(huì)鎖住當(dāng)前實(shí)例保證同一時(shí)刻只有一個(gè)線程能進(jìn)入修改方法。換句話說兩個(gè)線程同時(shí)往一個(gè)StringBuffer里追加內(nèi)容最后得到的數(shù)據(jù)不會(huì)出現(xiàn)內(nèi)存層面的混亂**比如數(shù)組越界、數(shù)據(jù)覆蓋、內(nèi)容壞掉等。但注意這個(gè)邊界——它只能保證“單次方法調(diào)用”的原子性。如果你在方法外面做了多步操作比如先append了學(xué)號(hào)再append了姓名中間再有其他線程插一腳那最終輸出的順序可能就是亂的。下面的代碼就是一個(gè)標(biāo)準(zhǔn)的“以為安全其實(shí)不安全”的例子StringBuffer logBuffer new StringBuffer(); // 線程A logBuffer.append(用戶登錄成功, userId).append(userId); // 線程B logBuffer.append(用戶登錄失敗, userId).append(userId);即使每個(gè)append都加鎖但A的兩次append可能被B的append插在中間最終日志內(nèi)容是“用戶登錄成功, userId123用戶登錄失敗, userId456”而不是兩條完整獨(dú)立的日志。要解決這個(gè)順序問題你得把“拼接整條日志”的操作放到一個(gè)synchronized代碼塊里統(tǒng)一加鎖而不是依賴StringBuffer自身。4.2 StringBuffer的性能代價(jià)不只是“慢一點(diǎn)”很多人以為StringBuffer只是比StringBuilder“慢一點(diǎn)點(diǎn)”這是另一個(gè)大誤區(qū)。鎖的開銷和臨界區(qū)的大小相關(guān)StringBuffer把每個(gè)方法都加鎖等于把性能壓在了每一次拼接上。在單線程環(huán)境下這個(gè)開銷可能不明顯但在一個(gè)大規(guī)模并發(fā)的日志系統(tǒng)里StringBuffer會(huì)因?yàn)轭l繁的鎖競(jìng)爭(zhēng)變成明顯瓶頸。我做過一個(gè)粗粒度的壓測(cè)單線程下StringBuffer的append速度大約是StringBuilder的60%~80%這個(gè)差距在并發(fā)環(huán)境下還會(huì)放大因?yàn)殒i的等待會(huì)讓線程實(shí)際執(zhí)行時(shí)間的占比大幅下降。所以我的建議非常明確如果只有一個(gè)線程在操作永遠(yuǎn)不要用StringBuffer。不要讓它出現(xiàn)在你的新代碼里它更適合作為歷史兼容類存在。4.3 StringBuffer里那個(gè)罕見的優(yōu)化toStringCache說來有意思StringBuffer在JDK 5之后其實(shí)引入了一個(gè)StringBuilder沒有的優(yōu)化toStringCache。它是一個(gè)緩存字段第一次調(diào)用toString()時(shí)會(huì)把當(dāng)前字符數(shù)組轉(zhuǎn)成String并緩存起來之后只要內(nèi)部數(shù)組沒變過后續(xù)的toString()直接返回緩存即可。這個(gè)設(shè)計(jì)是為了緩解“全鎖”帶來的性能問題。但是這里藏著一個(gè)坑如果toStringToString之后又繼續(xù)append緩存會(huì)被置空再toString時(shí)又要重新創(chuàng)建String。所以StringBuffer的“緩存”只在“拼完之后多次toString”的場(chǎng)景有效。如果拼一次、toString一次、再改一點(diǎn)、再toString的這種交替使用方式緩存優(yōu)化的收益就趨近于零。5. String底層的這些機(jī)制決定了你在面試中能不能答得出彩前面把三者的選型和性能邏輯講清了但String本身還有些底層機(jī)制值得單獨(dú)聊一聊。這些機(jī)制不僅面試愛問實(shí)際工作中也常在不經(jīng)意間影響你的代碼質(zhì)量和性能。5.1 字面量、new關(guān)鍵字與字符串常量池先看下面這段代碼大部分初級(jí)開發(fā)都能答對(duì)“a和b是相等的”但到了“為什么c不等于d”這里就開始卡殼了String a hello; String b hello; String c new String(hello); String d new String(hello); System.out.println(a b); // true System.out.println(c d); // false System.out.println(a.equals(c)); // true原因是直接用雙引號(hào)寫出來的字符串字面量會(huì)在字符串常量池中創(chuàng)建或復(fù)用對(duì)象而new String(hello)則會(huì)強(qiáng)制在堆內(nèi)存中創(chuàng)建一個(gè)新對(duì)象不管常量池里有沒有。這里有個(gè)細(xì)節(jié)值得留意new String(hello)創(chuàng)建的String對(duì)象內(nèi)部的字符數(shù)據(jù)其實(shí)是引用了常量池中“hello”那份數(shù)據(jù)的。所以嚴(yán)格來說new String真正開銷在“多創(chuàng)建了一個(gè)對(duì)象殼子可能多占一份引用”而字符本身在常量池和堆中是共享的。這也是為什么我們寫代碼時(shí)應(yīng)盡可能用字面量直接賦值而不是隨手new一個(gè)String——不必要的對(duì)象創(chuàng)建會(huì)造成無謂的堆內(nèi)存占用。5.2 intern()機(jī)制把堆里的字符串“扣”一份回常量池intern()是String提供的一個(gè)略顯冷門的方法但了解它的人減少了很多無謂的重復(fù)字符串內(nèi)存開銷。調(diào)用intern()時(shí)JVM會(huì)在常量池中查詢字符串是否存在存在就把常量池的引用返回不存在則把當(dāng)前字符串的引用放入常量池。JDK6及之前常量池放在方法區(qū)PermGenintern的行為是真正“拷貝一份字符串進(jìn)常量池”JDK7之后常量池被移到了堆區(qū)intern行為變成了“在常量池記錄一下堆里的對(duì)象引用”。這個(gè)變化帶來的實(shí)際影響是JDK7之后調(diào)用intern()并不會(huì)額外創(chuàng)建字符串副本只是在常量池里登記了引用。所以如果你有一段大量重復(fù)字符串的邏輯比如數(shù)據(jù)清洗時(shí)的城市名、狀態(tài)名合理使用intern()可以顯著降低堆內(nèi)存占用。但要注意intern()本身也有查找開銷在字符串?dāng)?shù)量特別大時(shí)常量池本身的維護(hù)和GC其實(shí)也有壓力。它適合“重復(fù)率極高”的場(chǎng)景不適合無腦亂用。5.3 為什么循環(huán)里不要用String累加真實(shí)場(chǎng)景的GC表現(xiàn)為了把這個(gè)問題說得更直觀我做一個(gè)簡(jiǎn)單的性能測(cè)試。用兩種方式循環(huán)拼接100萬次字符串方式一直接用str i方式二用StringBuilder.append(i)實(shí)測(cè)耗時(shí)差異在幾十倍到上百倍之間而且隨著拼接次數(shù)的增加方式一的耗時(shí)呈指數(shù)級(jí)惡化。GC日志里方式一會(huì)頻繁觸發(fā)Minor GC因?yàn)槊枯喲h(huán)都會(huì)產(chǎn)生中間String對(duì)象和StringBuilder對(duì)象方式二的GC次數(shù)明顯少得多。所以那些在面試?yán)锎稹白址唇佑肧tring就行編譯器會(huì)優(yōu)化”的人實(shí)際上只是背了個(gè)結(jié)論沒有真正理解優(yōu)化的邊界在哪。這個(gè)題的完整答案是單條語句編譯器可以優(yōu)化循環(huán)體內(nèi)部請(qǐng)自己動(dòng)手用StringBuilder別指望編譯器。6. 三者在不同JDK版本里的變化不只是性能那點(diǎn)事如果你以為這三個(gè)類從JDK 5之后就沒什么變化了那就小看Java版本演進(jìn)了。JDK 9開始String的底層存儲(chǔ)從char[]換成了byte[]這個(gè)改動(dòng)對(duì)整個(gè)字符串體系的性能和內(nèi)存都有深遠(yuǎn)影響。6.1 Compact Strings為什么JDK 9改成了byte數(shù)組在JDK 9之前String內(nèi)部用char[]存儲(chǔ)每個(gè)char固定占2字節(jié)。但現(xiàn)實(shí)中大多數(shù)業(yè)務(wù)字符串都是拉丁字符字母、數(shù)字、英文標(biāo)點(diǎn)完全可以用1字節(jié)表示。如果一律用2字節(jié)存空間浪費(fèi)一半。JDK 9引入Compact Strings機(jī)制后如果字符串內(nèi)所有字符都能用ISO-8859-1/Latin-1編碼表示單字節(jié)那么就用單字節(jié)數(shù)組存儲(chǔ)用一個(gè)coder字段標(biāo)記編碼方式如果包含中文字符等需要2字節(jié)的字符就自動(dòng)切換為UTF-16編碼存儲(chǔ)。這個(gè)改動(dòng)的直接收益是純英文和數(shù)字的字符串內(nèi)存占用直接砍半。這個(gè)改動(dòng)也間接影響到了StringBuilder和StringBuffer——它們雖然不是byte[]存儲(chǔ)但JDK 9之后它們?cè)诤芏鄬?shí)現(xiàn)上也做了適配優(yōu)化。整體上整個(gè)字符串體系的性能和內(nèi)存都受益于此。6.2 JDK 8到JDK 17的編譯器優(yōu)化變遷順便說一下編譯器對(duì)字符串拼接的優(yōu)化策略經(jīng)歷了幾次演進(jìn)。JDK 9之前主要是用StringBuilder做鏈?zhǔn)絻?yōu)化JDK 9之后引入了一個(gè)叫StringConcatFactory的機(jī)制默認(rèn)策略是indy它能把字符串拼接更靈活地延遲到運(yùn)行時(shí)處理。這意味著“編譯器一定把它轉(zhuǎn)成StringBuilder”這句話在JDK 9之后已經(jīng)不完全準(zhǔn)確了運(yùn)行時(shí)JIT可能會(huì)采用更聰明的策略比如直接預(yù)估緩沖區(qū)大小、甚至自動(dòng)決定是否用復(fù)制而不是擴(kuò)容。但這個(gè)優(yōu)化同樣有限制——它針對(duì)的是簡(jiǎn)單的、可內(nèi)聯(lián)的拼接表達(dá)式。放到復(fù)雜循環(huán)里編譯器依舊沒辦法幫你自動(dòng)合并依舊要手動(dòng)使用StringBuilder。所以我的一個(gè)建議是別過度依賴編譯器和JDK版本的優(yōu)化該手寫StringBuilder的時(shí)候老實(shí)寫。把性能掌握在自己手里而不是賭JIT的版本和策略。代碼的可讀性和性能保證比依賴某個(gè)JDK版本的“黑科技”更劃算。6.3 JDK 21中的字符串模板這個(gè)未來值得關(guān)注JDK 21引入了“字符串模板”的預(yù)覽特性比如這樣的寫法String name 小明; int age 20; String message STR.姓名:\{name}, 年齡:\{age};這有點(diǎn)像后來很多語言里的字符串插值寫起來比一堆a(bǔ)ppend拼接要直觀得多。但目前Java的字符串模板和StringBuilder不是替代關(guān)系它更多解決的是“可讀性”問題而不是“性能”問題。到了運(yùn)行時(shí)它仍然要經(jīng)過拼接的過程底層實(shí)現(xiàn)依舊依賴字符數(shù)組的擴(kuò)容和拷貝機(jī)制。我對(duì)字符串模板的態(tài)度是關(guān)注它但不必急著大規(guī)模使用。等它轉(zhuǎn)正并穩(wěn)定后配合模式匹配這些新特性確實(shí)能讓代碼寫起來更舒服。但在老項(xiàng)目里StringBuilder依然是那個(gè)最踏實(shí)的選擇。7. 實(shí)戰(zhàn)避坑指南我在真實(shí)項(xiàng)目里踩過的幾個(gè)字符串坑理論講了一大堆最終還是要落到代碼上。這一節(jié)我把自己在實(shí)際項(xiàng)目中踩過的、調(diào)過的、幫同事擦過屁股的幾個(gè)字符串相關(guān)坑拿出來聊希望能幫你繞過。7.1 坑一StringBuilder.reverse()的大坑——小心代理無關(guān)的“中央反轉(zhuǎn)”先說一個(gè)朋友在公司日志脫敏系統(tǒng)里踩的坑。需求是把身份證和手機(jī)號(hào)中的數(shù)字做倒序展示他們直接這樣寫String mobile 13800138000; String masked new StringBuilder(mobile).reverse().toString();乍看沒問題反轉(zhuǎn)后恰好是把尾號(hào)放在前面邏輯上確實(shí)做到了“倒序”。但問題是他們忘了需求里其實(shí)要求的是“只反轉(zhuǎn)部分位”而不是“整串反轉(zhuǎn)”。因?yàn)镾tringBuilder.reverse()是對(duì)整個(gè)字符序列做反轉(zhuǎn)如果把“13800138000”整體反轉(zhuǎn)就成了“00038100831”身份證里的歸屬地信息全亂了。這種坑特別隱蔽因?yàn)槟闳庋劭唇Y(jié)果“確實(shí)是倒的”但業(yè)務(wù)含義卻錯(cuò)了。所以用reverse()前一定要確認(rèn)你的業(yè)務(wù)場(chǎng)景是不是“整個(gè)字符串整體反轉(zhuǎn)”。如果你要的是“后四位放在前面”這種局部反轉(zhuǎn)請(qǐng)先substring再反轉(zhuǎn)拼接而不是直接reverse整個(gè)串。7.2 坑二substring的底層變化和內(nèi)存泄漏隱患JDK 7之前JDK 7之前String.substring()返回的子串會(huì)共享原始字符串的底層char[]數(shù)組而不是拷貝。這在當(dāng)時(shí)是為了節(jié)省內(nèi)存但如果原始字符串很大、子串很小且被長(zhǎng)期持有那么這個(gè)子串會(huì)“拽住”整個(gè)大數(shù)組不讓GC回收——這就是舊JDK版本里非常有名的內(nèi)存泄漏Case。JDK 7之后substring改為創(chuàng)建新數(shù)組并拷貝內(nèi)容不再共享底層數(shù)據(jù)。如果你的項(xiàng)目還在用JDK 6或更早的版本雖然現(xiàn)在很罕見遇到大字符串頻繁substring長(zhǎng)駐內(nèi)存時(shí)要格外小心。即使在新版本里頻繁substring也會(huì)產(chǎn)生拷貝開銷這也是在一些高性能場(chǎng)景用StringBuilder.delete()或subSequence()來替代的原因。7.3 坑三空字符串拼接導(dǎo)致的結(jié)果難排查常見的錯(cuò)誤還有這類邏輯StringBuilder prefix new StringBuilder(); if (condition) { prefix.append(VIP_); } String finalName prefix.append(userName).toString();如果你在condition不滿足時(shí)直接用了finalName最終拿到的其實(shí)是userName本身——因?yàn)閜refix是空的。這類“空拼接”的問題在拼SQL時(shí)特別致命你拼了一個(gè)WHERE 11 AND ...開頭但某個(gè)字段沒傳值最后拼出來的SQL誰能一眼看出問題我的經(jīng)驗(yàn)是在StringBuilder拼接的場(chǎng)景每append完一個(gè)動(dòng)態(tài)片段至少打一行debug日志確認(rèn)當(dāng)前sb的內(nèi)容。尤其是剛接手別人的拼接代碼、或在自己寫了超過5個(gè)append的長(zhǎng)鏈時(shí)。7.4 坑四格式化字符串別忘了String.format的隱藏成本String.format()是一個(gè)常被誤當(dāng)成“拼接優(yōu)化”的方法。它的底層實(shí)現(xiàn)極其復(fù)雜解析格式字符串、生成Formatter、處理各種占位符和參數(shù)類型轉(zhuǎn)換。在低并發(fā)場(chǎng)景下可讀性帶來的價(jià)值遠(yuǎn)大于性能損失但如果你在核心熱路徑里用它構(gòu)造日志就要考慮換成手動(dòng)append了。我處理過一個(gè)案例一個(gè)系統(tǒng)每秒要打上千條審計(jì)日志每條日志用String.format(user%s, action%s, cost%sms, ...)拼接。實(shí)際邏輯對(duì)比后用StringBuilder重構(gòu)后耗時(shí)下降了接近一個(gè)數(shù)量級(jí)。核心熱路徑上的字符串構(gòu)建真的沒必要為了可讀性犧牲這么多性能——可以用模板字符串或者分步append可讀性和性能之間往往有更好的平衡點(diǎn)。7.5 坑五不要用StringBuffer做日志脫敏最后補(bǔ)充一個(gè)StringBuffer相關(guān)的坑。有人為了“線程安全”在日志脫敏系統(tǒng)里把每一次脫敏后的結(jié)果都往一個(gè)StringBuffer里append然后想著反正它是線程安全的多個(gè)線程寫也沒事。結(jié)果日志順序完全亂成一鍋粥。這里又把4.1節(jié)那個(gè)邊界條件拿出來強(qiáng)調(diào)一遍StringBuffer的線程安全不等于業(yè)務(wù)順序安全。如果需要保證“多條日志按提交順序完整輸出”你需要的不是StringBuffer而是隊(duì)列單線程消費(fèi)或者每個(gè)線程獨(dú)立的緩沖區(qū)。線程安全是一個(gè)很基礎(chǔ)的級(jí)別別把它當(dāng)萬能刀。8. 面試官看這段代碼的眼神從String到StringBuilder再到StringBuffer的“送命題”寫了這么多年Java我參加過不少面試也面過不少候選人。這部分梳理幾個(gè)我在面試時(shí)最常用來考察字符串理解的“送命題”附上完整思路對(duì)你準(zhǔn)備面試應(yīng)該有幫助。8.1 題目一為什么String是不可變的常見回答因?yàn)橛昧薴inal修飾、底層char[]/byte[]也被final修飾所以不能改內(nèi)容。這個(gè)回答只能算及格。想答出彩要補(bǔ)充三方面的理由安全性字符串被大量用作參數(shù)、類名、配置項(xiàng)、網(wǎng)絡(luò)協(xié)議字段不可變保證不會(huì)被惡意修改。性能優(yōu)化基礎(chǔ)字符串常量池、hash緩存、多線程安全共享都是建立在不可變前提上的如果可變這些機(jī)制全都會(huì)崩。線程安全不可變對(duì)象天然線程安全任意線程隨意共享引用都沒有數(shù)據(jù)競(jìng)爭(zhēng)問題。8.2 題目二String、StringBuilder、StringBuffer怎么選完整答案應(yīng)該拆成三個(gè)維度內(nèi)容標(biāo)識(shí)不變、需要共享復(fù)用用String。比如常量、配置值、方法參數(shù)。單線程下需要高頻修改、拼接用StringBuilder。尤其循環(huán)體和日志場(chǎng)景要記得盡量預(yù)分配容量。多線程共享同一個(gè)可變緩沖區(qū)時(shí)考慮StringBuffer但還要想清楚順序安全的邊界更推薦用并發(fā)數(shù)據(jù)結(jié)構(gòu)自行保證整體邏輯。如果只是每個(gè)線程各拼各的優(yōu)先StringBuilder。8.3 題目三字符串拼接的“編譯器優(yōu)化”到底優(yōu)化了什么面試時(shí)能答到“javac會(huì)把轉(zhuǎn)成StringBuilder”算及格能往下說才行優(yōu)化只局限在單條語句內(nèi)部循環(huán)體內(nèi)依舊會(huì)創(chuàng)建大量中間對(duì)象。JDK 9之后默認(rèn)優(yōu)化方式從“構(gòu)造StringBuilder”變成了StringConcatFactory的indify機(jī)制到運(yùn)行時(shí)JIT階段再?zèng)Q定實(shí)際拼接策略。無論是哪種優(yōu)化本質(zhì)都是“可變緩沖區(qū)一次性拼接”和手寫StringBuilder思路一致只是邊界和策略不同。8.4 題目四字符串拼接性能和哪幾個(gè)因素相關(guān)幾個(gè)核心點(diǎn)按重要程度排序拼接次數(shù)每多一次拼接就多一分?jǐn)U容和拷貝成本。初始容量預(yù)分配能顯著減少擴(kuò)容次數(shù)。JDK版本JDK 9之后的Compact Strings對(duì)純拉丁字符節(jié)省一半內(nèi)存。并發(fā)度StringBuffer的鎖競(jìng)爭(zhēng)在并發(fā)下會(huì)放大性能問題單線程用StringBuilder。這些問題實(shí)際上把前面聊的所有知識(shí)都串在了一起。能把這些講清楚面試官通常就不會(huì)再在字符串這塊糾纏了——你再深入一點(diǎn)比如講講intern()的JDK版本差異或者講講JDK 9底層byte[]的編碼判斷邏輯已經(jīng)超過大多數(shù)候選人的深度了。9. 到底該怎么寫代碼我的一份可落地的String編碼規(guī)范講了這么多原理和坑是時(shí)候把這些沉淀成一套能直接落到團(tuán)隊(duì)里的編碼規(guī)范了。下面是我自己在項(xiàng)目里會(huì)強(qiáng)制自己和團(tuán)隊(duì)遵守的一套String使用規(guī)則你可以直接抄走按需調(diào)整。原則一能用字面量絕不用new。// 錯(cuò)誤 String s new String(hello); // 正確 String s hello;原則二單條語句的少量拼接用多條/動(dòng)態(tài)拼接用StringBuilder。// 單條語句可讀性優(yōu)先編譯器能處理好 String log user userId , action action; // 循環(huán)或復(fù)雜拼接 StringBuilder sb new StringBuilder(256); for (Item item : items) { sb.append(item.getName()).append(,); }原則三StringBuilder需要預(yù)分配容量時(shí)先算一個(gè)合理上界。比如你知道最大可能有100條記錄、每條按50字符算就按100 * 50來初始化甚至可以加一點(diǎn)余量。原則四純多線程共享且確實(shí)要安全修改時(shí)優(yōu)先考慮用隊(duì)列單線程消費(fèi)而不是StringBuffer。StringBuffer只在“你確實(shí)只需要一個(gè)多線程共享的字節(jié)序列、且接受順序亂的可能”時(shí)才使用。大多數(shù)場(chǎng)景用隊(duì)列會(huì)得到更清晰的設(shè)計(jì)。原則五高性能路徑上的日志/報(bào)文構(gòu)建不要用String.format()和字符串拼接。直接在熱路徑上用StringBuilder把所有信息一步一步append進(jìn)去。這個(gè)優(yōu)化看起來很小但積少成多在高并發(fā)的服務(wù)端里能省下不少CPU和GC時(shí)間。10. 最后聊一點(diǎn)實(shí)際體驗(yàn)我自己寫代碼有個(gè)習(xí)慣在拿到一段新需求時(shí)先判斷這個(gè)字符串將來會(huì)不會(huì)被修改。如果不會(huì)——比如一個(gè)請(qǐng)求參數(shù)、一條配置項(xiàng)、一個(gè)數(shù)據(jù)庫字段名的字符串——就用String享受不可變帶來的所有好處如果會(huì)——比如動(dòng)態(tài)拼SQL、拼HTTP報(bào)文、拼日志——就直接上StringBuilder預(yù)分配容量全程不切String直到最終toString。這套思維模式就是String、StringBuilder、StringBuffer三兄弟在真實(shí)世界里的分工邏輯String負(fù)責(zé)當(dāng)“穩(wěn)定的載體”StringBuilder負(fù)責(zé)“高效的加工”StringBuffer只負(fù)責(zé)“歷史兼容和多線程兜底”。記住這個(gè)分工面試題和實(shí)際代碼就都跑不出你的掌心。如果這篇文章對(duì)你有幫助或者你在項(xiàng)目里也遇到過字符串拼接相關(guān)的性能坑、GC問題歡迎留言交流。順手給自己提個(gè)醒下次看到負(fù)責(zé)拼接的代碼先別急著寫先想想——這個(gè)字符串會(huì)不會(huì)變
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
中文字幕一区二区三区蜜臀| 校园春色制服丝袜中文字亚洲 | 91美女视频直播| 91在线综合网| a在线观看| 国产av强奸美女| 99久久99久久免费精品蜜臀| 欧美三四五区| 综合亚洲网| 亚洲人妻中文在线视频| 久久久97| 亚洲无992tv| 果冻传媒A片麻豆熟妇人妻| 青青草狠狠撸| 天天天操天天天爱| 日本道人妻久久久在线不卡色视频| 91久久久视| 青青草日逼视频| 黑丝内射一区二区三区| 噜噜在线| 欧美无圣光在线| 91在线免费观看处女| 亚洲情色1区| 中文字幕 一区二区 亚洲无码| 2020中文字幕| 啊啊啊97视频| 妇女乱色二区| 91免费看一区二区三区 | 人妻久热在线| 欧美色图 人妻| 久久色AV线| 中国韩国明星一极片一区乱码毛片人妻熟女一区二区三区 | 中字幕人妻一区二区三区| 超碰在线人人射| AV色五月| 亚洲熟女诱惑| 91视频国品一二三区| 亚洲啪啪综合?v一区综合精品区| 十八禁电影伊人网| 91激情国产| 欧美一区二区三区黄色影视| 99久久无色码| 欧美A√综合网| 欧美aⅴ99久久黑人专区| 亚洲小电影免费涩涩成人在线高清| 99热导航| 伊人成人中文字幕久久网| 1000部熟女视频在线观看| 五月天黄色av| 青娱乐国产精品| 久久久性爱| 伊人991| 伊人久久88国产女| 一级做a爰片性色毛片久久| 国产不卡片| 国产不良强奸视频免费看| 九九九九九用不成了| 日本视频在线观看污污污| 91天天综合| 日韩精品啪啪啪| 色天使大香蕉| 色999人与兽| 欧美日韩性爱无码| 天天天天做夜夜夜夜做| 久久东京热久久| 综合色图,成人综合网| 97爱综合| 欧美78| 天天色黄色影院天天操| 色欧美在线| 日本123区操B视频| 亚洲欧美另类激情小说| 超碰色中文| 五月天丁香婷婷综合网站| 超碰9 7女人| 国产67194| h无码动漫在线观看| 懂色av中文字幕| 日日干夜夜欢| 视频国产精品未满十八禁止在线观看| 五月丁香在线| 97精品国产| 国产丝袜美女诱惑| 2019久久久久久久久福利| 国产欧美成人精品| 天美传媒av 在线| 亚洲日韩精品久久久久一区壹牛 | 国产SV一线| 国产熟女完整版中字| 欧美色图99| 国产精品情侣啪啪| 国产精品国产拍高清AV| 飘花国产午夜精品不卡| 国产97亚洲| 国产免费久久精品99re韩国| 久热这里| 日本熟女中文字幕一区| 97这里只有精品| 青青草玖玖爱| 97精品视频网站| 午夜大香蕉| 在线观看一级α片刺激高潮视频| 91模特在线观看| 黑丝日韩av丝袜av| 啊啊啊啊视频免费| 天天日B狠狠操| 图片区小说区| AV不卡在线| 男人的天堂 在线一区| 久久久内射良家| 春色校园综合网| 日韩三级一区| 东京热激情视频一二三区| 日逼国产| 手机在线人成免费视频| 国产精品探花视频| 亚洲高清无码在线桃色| 精品一啪| 国产超碰人人操| 亚洲精品中文字幕一区在线视频| 精品一区二区人妖| 在线观看国产黄色| 久久丁香五月天| 欧美日韩成人在线| 97超碰69| 日韩三级在线观看mp4| 熟妇熟女一区二三区| 99热免费| 爱爱久久| 少妇三p| 日本不卡一二区| 男人的天堂va| 性色生活片久久毛片婬片免费放女人一级毛片 | 偷拍99| 天天日天天看| 性爱综合一区二区| 96久久精品一二三区色欲| 精品一区二区成人动漫| 富二代亚洲精品99| 日日嗷| 久久久不卡| 91看黄片| 色婷婷导航| 欧美日韩免费专区在线| 春色综合免费| 91精品人妻偷情| 亚洲成?V人片在线观看福利| 99热97| 97精品综合久久网| 久久大| 日韩乱伦影音先锋| 国产AV天美| 欧亚 另类 久| 天堂中文日本在线观看| 国精综合一二三区影视| 亚洲一区二区在线观看91| 一本一道vs波多野结衣| 国产男女无套97| 97se亚洲综合自| 欧美日韩国产高清在线一二三区 | 亚洲综合中文字幕有码 | 四虎精品永久在线观看| 成人性爱全视频观看| 日韩三级网址| 日韩无码第3页| 亚洲熟女乱色一区二区三区久久久| 九九久久99| 伊人女女资源在线观看| aaa亚无码专区| 男人的天堂啪啪| 友优传媒精品在线一区二区| 久久免费中文字幕在线观看| 玖色AV| 自拍盗摄一区| 俺去俺来也在线www| 综合色一区三区二区| 亚洲91亚洲| 国产色呦呦| 97在线免费视频观看| 青青草国产亚洲精品久久| 亚洲古典另类欧美在线| 免费国产电影一区二区| 黄网色一区二区三区四区精品| 亚春色色| 亚洲图片 激情小说| 欧美亚洲综合色| 久久直播国产| 视频国产欧美在线播放| 欧美97在线欧| 97亚洲色图| 精品视频久久区| 午夜精品99久久久久传媒| 国产成人www免费人成看片| 亚洲丝袜少妇在线| 久久婷婷苹果| 久久精品无码不卡| 久久久久久久9最新免费视频观看| 精品一区二区啪啪啪| 亚洲色图亚洲无码强奸乱伦| 日韩亚洲中文有码视频| 影音先锋少妇| 欧美日韩*字幕一区| 美欧色综合| 肉丝中文无码高清| 精品妇操一区二区三区| 亚洲成人精品久久久| 屌逼麻豆| 日韩久久三区| 五月婷婷丁香六月| 色婷婷基地| 懂色AV蜜臀无码精品APP | 成人资源中文字幕在线观看天天| 国产高清免费不卡av| 欧州一区二区三区四区| 翔田千里无码一区| 久久久久中出| 欧美极品女人的天堂| 亚欧性爱在线无码| 九月婷婷久久| 色婷婷五月天| 日韩女优在线| 中文字幕十五区| 亚洲色性情三级| 婷婷伊人一区| 国产精品午夜成人福利| 大香蕉中文aV在线| 亚欧洲一区二区视频| 精品乱码久久久久| 91精品91久久久久77777| 亚欧美综合| 日韩本不卡视频在线观看 | 欧美中文字幕日韩在线| 欧美性爱18观看| 欧美五十路熟| 亚洲暴力强奸AV| 新婚人妻扶着粗大强行坐下| 日本色婷婷| 欧美久久九九| 91亚洲丝袜| 97精品人妻一二三四| 日本一线产区和二线产区伦理片| 性色aV一区二区三区噜噜| 神马久久久久久久| 天天操天天干一区二区 | 国产九九久久久精品| 美女淫穴| 少妇人妻激情四射| 豆花视频操逼网址| 国产 亚洲 丝袜 制服| 激情五月天丁香社区| 婷婷五月在线视频| 久久宗合亚洲| 十八禁啪啪视频| 黄色大片免费在线| 精品久久一区二区三区四区五区| 欧美97在线观看| 老女人91| 2017av无码免费无线播| 8050无码八戒| 夜夜操老骚逼视频网站| 人妻人久久精品中文字幕| nuu12国产麻豆精品| 国产伦精品一区二区三区在线观| 加勒比在线视频| 久久只有精品一区二区三区| 偷拍亚洲情色| 91大神精品长腿在线观看网站| 日韩性爱视频在线免费观看| 欧美日不卡| 歐美性天天| 国产国产亚洲一二三久久| 97免费在线| 国产操逼逼网| 亚洲。日韩。欧美| avav青青草久久夜| 亚洲精品影视老司机| 国产suv精品一区二区四| 超碰97欧美日韩| 日韩免费中文字幕视频| 九月婷婷久久| 视频二区熟女人妻| 91精品亚洲内射孕妇| 97五月天| 一卡二卡在线播放| 国产精品蜜乳AV| 91九九九逼| 精品视频一区二区| 天天爽天天| 中文字幕第95页| 久久一区二区高清免费| 北条麻妃性愛视频| 成 人 A V免费视频在线观看| 国产一级αv免费看片| 天美欧美国产| 欧美成人一级免费电影| 牛牛久久国产精品视频一二三 | 成人性交免费视屏| 黄色av片三级三级三级免费看| 国产原创自拍| 国内精品久久国产,www香蕉久久五月丁香,亚洲欧美日韩精品永久在线,日本精品一 | 91美女国产在线| 999色欧美中文字幕| 秋霞无码av鲁丝片一区| 综合久久99亚洲人妻中文在线| 日韩成人精品| 人妻 制服 日韩 中文 在线| 国产中出内射一区二区| 91精品国产综合久久久蜜臀| 日韩少妇无码| 啊啊啊啊视频免费| 人妻精品视频一区二区三区| 国产精品青青草| 亚洲超碰97| 91精品国产综合久久久蜜臀| 欧美成人免费在线观看| 超碰在线974| 在线观看一级α片刺激高潮视频| 九九热超碰97亚洲最新香蕉| 亚洲自拍天堂| 亚洲欧美天| 爱我干综合| 国产9l 大屁股| 中文激情网| 诱惑网综合| 九九热九九热| 午夜无码精品免费看性色| 后入福利视频| 五月婷婷深深爱| 九七超碰| 品亲网欧美品亲网| 日本熟女中文| 91在线免费精品视频| AV一二区| AA特级绝黄| 啊啊啊啊啊啊在线| 日夜久久久九九九久| 日韩国产乱子伦App| 大香蕉手机在线| 最新欧洲欧美日本激情网站| 亚洲图片激情综合另类| 久9综合在线| 综合色图,成人综合网| av黄图片在线观看| 欧美国产精品| 无码精品啪啪啪一区二区三区三州| 欧美做爰无码A片视频| 久久久96| 欧美最婬乱婬爆婬牲视频| 亚洲情色第一页| 国产欧美精选自拍一区| 天天干18禁| 日韩电影天堂视频二区三区| 老熟女91av| 久久av成人无码免费| 啪啪啪亚欧美视频| 中文字幕精品专区搜索结果91| 丁香婷婷啪啪| 欧美老妇曰批的视频| 神马麻豆福利院| 国产精品久久久九九九| 欧洲乱码一区二区| 超碰狠狠操| 脫衣舞一区二区三区| 极品肉射| 97久久国产精品| 91女网站| 91丨九色丨熟女高潮| 三级AV入口| 97免费在线观看| 都市激情人妻一区二区青青操视频 | 操逼国产免费| 久草尤物| 日产操逼| 五月天伊人网| 91n处女在线观看| 九九热精彩视频| 国产精品久久久视频| 狠狠爱综合| 不卡一区二区日本视频| 上海一级黄片| wwwxxx日本爽| 性色生活片久久毛片婬片免费放女人一级毛片 | 91超级碰| 色五月激情网| 另类天堂| 色五月首页| 色婷婷九月天天综合| 中文字幕在线观看永久| 久久九九一区二区三区成人| 思思热在线cao| 久久午夜伦| 天天舔天天 | 嗯嗯嗯,草死我| 五月天婷婷基地| 日亚韩精品视频二区三| www.超碰在线| 天天日日夜夜| 久久久com| 中文字幕在线观看网页| 亚洲AO在线| 欧美一区二区情色| 精品国产国产AV| 99re99视频在线免费观看| 男人久久精品| AV色五月天| 一级免费精品| 97免费视频在线| 蜜臀一区二区三区亚洲最新章节在线观看 - 高清蜜臀一区二区三区亚洲全集播放 | 日韩日本欧美在线观看| 欧美亚洲自拍另类人妻| 乱伦图一区| 黄片无码在线制服| 蜜臀国产AV中文字幕| 韩国一区二区精品亚洲| 中文字幕78| 中文字幕精品亚洲熟女| 色97干| 蜜桃狠狠色伊人亚洲综合网站| 亚洲无992tv| 久久精品日韩| 91粉芽高清在线一区二区| 美女上床网站| 97免费在线观看视频| 人妻性爱一区二区| 在线可观看的黄色网址| 大香蕉在线视频15| 亚洲 综合 第一页| 2017天天拍大香蕉| aⅴ日韩成人电影av在线免费看av大全| 狠狠干婷婷| 国产大片精久久久久久| 人人九九精| 天天噜| 上海一级黄片| 欧洲无码一区二区| 久久精品操| 久久精品 六十路 熟女 欧美| yellow网站免费观看日韩高清无码| 中文自拍欧美影视| 宗合情欲网| 97在线视频观看免费| 操逼网站网站| 另类天堂| 中文久久96| 97超碰超碰| 91社操逼| 天天干2019| 久超碰这里只有精品| 欧美一级A一级a爱片久久| 强奸乱伦中文字幕AV| 1956日韩精品| 亚洲熟女人妻中文字幕一区二区| 国产精品自在线发布| 好淫网一二三视区| 伊人91| av无码精品久久久久| 九九无码久久精品视频| 久久久亚洲精品中文字幕人妻| 操啊国产| 2020视频1区2区3区| 丰满人妻一区| 超碰这里只有精品| 欧美天天性| 久久精品三级影视| 久久久久久久久国产| 亚洲精品乱码线路中文字幕| 亚洲 图片 综合91| 久久久久久999| 韩国午夜理伦三级好看| 性性久久| 最新国内自拍av免费| 久久五月份| 久久伊人影院| 人妻丝袜无 码视频专区| 啊啊啊啊啊舒服| 中国少妇XXXX做受| 欧美性生活内射| 老外又粗又长一晚做五次| 久久久工口| 中文字幕99999| 99激情| 91N综合网| 牛黄色久午久| 日日摸日日弄日日拍| 一区在线国产播放| 国产伊人精品在线| 激情综合五月天| 亚洲综合有码| 欧美日韩情色一区二区| 一区在线精品中文字幕| 欧美亚洲国产自久久| 岛国黄片网站| 日本孕妇孕交| 亚洲AV永久无码一区仙野| 激情婷婷丁香网| 日韩无码专区| 免费人成毛片乱码| 欧美在线视频播放| 丁香五月婷婷基地| 国产传媒av天美传媒在线| 天天淫人人妻日日色| 91精品国产91久久福利| 婷婷九月国产| 中文字幕一区av| 女沟厕偷窥piss小便| 青青操少妇| 国产无马视频| 一本久道久久综合狠狠爱一密臀精 | 女同女同恋久久级三级| 黑白配性爱AV成| 天美传媒国产原创中文字幕亚洲欧美另类 | 国产v片在线免费观看| 啊啊啊好大好湿| www欧美性爱| 国产传媒日韩| 人人搡人人肉久久精品| 成人av免费观看| 中日韩免费看男女操逼大全| 欧美色图 人妻| 天天色,天天干,天天干| 亚洲欧美综合区自拍另类| 啊灬啊灬啊灬啊灬高潮奶出了免费视| AAA久久| 人妻一区二区三区四区视频| 91麻豆一二三区| 91啪啪视频| 中文字幕AV乱伦| 91天天美女| 欧美老熟另类| 成人av动漫在线观看| 欧美精品三级黄片| 夜夜无码| 在线亚洲精品久久久| 精品久热| 最新中文字幕精品在线| 中文字幕精品探花视频| 99热这里都是精品| 国产精品蜜臀久久久久无码AV| 国产一区二区成人av在线播放| 色综合超碰超| 美女裸体麻豆天美蜜桃91| 91九色在线| 一区二区三区黄片免费观看| 国产后入| 97美日韩视频| 91美女国产在线| 9久久美女首页| 超碰久久.com| 久久蜜色情在线视频xxx免费观看| 久操精品网| 草草网站影院白丝内射| 大二网站亚洲| 中文字幕三四区| 蜜臀99久久国产| AV久日| 亚洲成人妻日韩在线| 爱射综合| 女优视频第10页| 大香蕉五月天婷婷| 亚洲熟女av日韩熟女| www.久久最新地址| 欧美不卡二区| 玖玖玖玖精品国产剧情| 秋霞久久亚洲精品成人| 91午夜无码| 国产AV色黄看到爽| 先锋激情∨在线视频播放| a片久久久久久久久久久久 | 91九九九小逼| 久久精品天美| 97色色色综合网站| 99re69| 久久久久一本一区二区青青蜜月| 任我爽视频在线观看| oumeisetu综合| 欧亚综合一卡二卡中文字幕| 久久一区无码| 91麻豆天美传媒HD| 九九九九免费高| 国产女人9999| 大香蕉92| 啊啊啊啊免费视频| 国产精品久久久久久久久久久久| 偷拍亚洲| 在线无码视频| 国产小黄片在线免费观看| 性色av网站| 亚洲精品国产精品乱码不99| 国模一区二区三区| 性色高清在线| 97网址97| 阿姨一区二区免费视频-高清正片西瓜视频下载app-T450AV | 亚洲毛片基地专区| 久久国产在线一区二区| 欧美人与性动交a美精品| 日韩欧美亚洲一区二区三区影院| 九九激情网| 成 人 影视 一区 二区 三区 四区 | 狠日操| 特级丰满少妇一级AAAA爱毛片| 91精品伊人久久久大香线蕉91| 免费一级视频特黄色大片| 成人综合色网| 欲香欲色天天天综合和网| 99re综合伊人| 尤物视频视频官网| 人人爱人人操人人性| 在线只有精品| 四虎视频在线观看| 校园春色 亚洲| 欧美真人抽搐一进一出gif| 玖玖玖玖精品国产剧情| 你操综合| 国产精品午夜精品| 久久久久亚洲熟妇熟女| 秋霞欧美性爰视频| 熟女中出视频| 亚洲黄色AV电影| 成全在线观看免费观看| 黄色网址久久精品欧美喷水| 亭亭在线资源| 欧美高清18A片| 午夜精品久久久久久久99蜜桃一| 伊人色综合超碰| 97色操| 国产操偷| 久久久久ab| 亚洲自拍97| 无码抄逼网| 裸体1区| 污色区网站| 99久久婷婷| 欧美激情久久久久| 国产亚洲深夜激情| 日本三级中国三级99人妇网站| 亚洲第91页 | 天堂v无码免费视频| 丁香五月电影| 日日AAvv| 强奸乱伦麻豆| 精品9区| 中文字幕精品一区二| 色婷婷综合久久久久中文国产精品一区中文字幕,国产福利电影一区二区三区 | 欧美日韩青操| 啊啊啊啊啊舒服| 一本一道vs波多野结衣| 操逼片国产| 啊啊啊好湿久久| 极品另类| 亚洲日本成人动漫| 青青五月天| 强免费黄色网址| 热热色色综合| 亚一综合久久久久久久久久| 国产熟女二区| 五十路三级片| 蜜臀aV午夜一区二区三区| 91影库| 欧美日韩大陆黑人少妇99| 日韩精品在线视频,日韩精品……| 久久婷五月天| 久久9精品| 五月天婷婷综合网| 天美传媒婬乱| 一区=区三区视频| 欧美Ⅴ性爱| 欧洲乱码一区二区| 国产av波波国产精品| 狠狠躁天天躁日日躁| 久久久亚洲高清不打码| 色踪合AV| 9久久精品| 99夜夜操| 人人爽夜夜操| 男人a天堂手机在线版| 加勒比性爱成人在线| 日本国产成人亚洲精品无码| 亚洲天堂无码| 91蜜臀人妻中文字幕在线| 99ri精品| 欧美一级在线观看成人| 99re69| 亚乱色| 少妇大屁屁| 蜜臀久久99精品久久久久久久久| 伊人网青青| 无码人妻系列少妇| 丁香五月婷婷基地| 日欧操屄| 国产日韩中文字幕欧美| 亚洲 综合 欧美| 99视频这有这里有精品| 骚日日av| 视频在线观看一二三区| 日韩欧美综合激情| 久久 精品| 伊人aaa| 激情婷婷| 97在线精品观看视频| 亚洲,欧美,综合网| 色91综合网| 欧美一区二区日韩三区| 亚洲午夜免费狠狠干| 精品97久久| 亚洲天天操| 99色婷婷| 国产精品亚洲色婷婷久久久| 久草精品视频| 久久久久9999| 久久久久久久强迫| 日韩有码回春沙龙第一页| 激情丁香五月婷婷| 亚洲91在线播放影院| 一二三区精品视频| 欧美激色| 中文字幕一区 二区三四五 区日 日骚| 老熟女网站| 偷拍综合亚洲| 嗯啊不要啊在线 | 国产一国产一级毛片古装| 97内射偷拍| 精品亚洲国产成人AV制服丝袜 | 97超碰人妻| 超碰97久久观看| 五月婷婷影院| 3P乱轮视频| 欧美一区二区三区不卡高清视频 | 国产免a费看黄片在线| 78精品| 精品国产一区二区三区久久久蜜臀| 91人妻素女| 亚洲 欧美 日韩 国产一区二区| 国产熟女自拍| 欧美青青视频| 九九久久首页| 亚洲乱熟女一区二区三区大香蕉| 69XX一中文字幕人妻91| 竹菊一区二区三区AV线| 粉嫩久久久久| 欧美日日夜夜| 天综合中文| 激情综合亚洲| 国产精品自在自拍视频| 色综合久久av| 国产成人91一区二区三区| 欧美亚洲首页| 色原狠狠天天天| 啊啊啊好多水| 久久大香蕉97| 日本高清视频在线观看黄已三辽| 欧美 综合 亚洲| 91黑丝美女| 国产农村妇女精品1区二区| 天天干美少妇一区| 人人操AV| 亚洲中文字幕97久久精品少妇| 五月天黄色激情视频| 中文字幕精品日韩中文字幕| 一级AV性爱| 午夜男女爽爽大片免费观看| 国产精品女aA片爽爽视频| 老妇女91| 亚州男人天堂| 欧美色青| 丁香七月婷婷| 操逼网站网站| 亚洲A曰本VA欧美VA视频| 亚洲国产精品成人综合| 欧美呦呦性爱| 99久久精品无码一区二区| 国产树林里野战在线看| 啪啪一区| 嗯嗯啊啊操死我| 午夜福利在线视频1000| 久久色AV线| 超碰超碰超碰超碰的大鸡吧操黑丝袜| 久久久日本电影| 欧美亚洲自拍另类人妻| 久久直播国产| 99热婷婷| 日本不卡码黄色| 国桃视频产巨乳精品一区二区在线| 亚洲男人天堂视频| 神马午夜久久| 天天操人人操狠狠插| 久久精品国产亚洲AV无码电影| 亚洲夜夜欢无码一区二区| 国产人妻精品久久久一区二区三区| 国内精品久久国产,www香蕉久久五月丁香,亚洲欧美日韩精品永久在线,日本精品一 | 裸体美女免费看网站青草| 久久色一区| 欧美手机在线综合| 欧美天天弄| 中文字幕乱在线伦视频中文字幕乱码在线 | 欧美性生活内射| 日本道人妻久久久在线不卡色视频| 美女诱惑一区| 日韩卡一卡二卡三在线| 五月婷婷综合在线| 久久大精品乱码视频人妻熟女| 亚洲校园激情| 色哟哟AⅤ| www久| 国产十八禁视频| 精品一区二区三区丰满熟女-亚洲欧美一区| 天天射天天| 99爱精品| 欧美日韩亚洲电影| 国产色产精品在线观看| 欧美成人黄网色网站| 麻豆区99999| 天美传媒精品久久视频| 艹精品| 欧美在线官网| 97在线视频免费看| 色噜噜精品一区二区三| 日本不卡高清免v欧美日韩在线观看| 丁香7月婷婷| 亚洲日本激情| 99色悠悠| 国产馆| 亚洲欧美国产其他二区| 人妻熟女一区二区三区在线| 精品午夜福利| 91日本在线观看| 狠操91,com| 26uuu欧美日韩| 国产乱婷婷精品二区三区| 婷婷人妻激情| 精品一二三区久久AAA片| 亚洲男人的天堂在线看| 亚洲一区日韩精品| 亚洲乱色视频一区、二区在线| 久久二| 国产亚洲99久久精品| 精品国产综合久久福利,热99这里有精品综合久久,99热这里只有免费国产精品,精 | 五月天伊人| 干b网| 亚洲av淫乱| 龙兴卡官方查询| 中文字幕一区二区日韩网| 蜜桃久久久久久久| 国产视频人人网| 女人天堂AV五区在线| 中文字幕在线免费观看视频| 超碰夫妻97| 免费一级a毛片久久久久久鸭绿欲| 人人爱夜夜爱| 欧美大波激情xxxx| 国产AV天美| ,成人免费啪啪视频| AV丝袜少妇| 精品国产91av一区二区三区| 亚洲AV不卡在线观看尤物| 国产亚洲精品激情| 97色色,97综合| 亚洲中文一区二区三区| 色眯眯av| 91精品久久综合熟女| 日韩电影中文字幕| 人妻少妇色综合| 欧美亚洲情色| 亚洲天堂自拍| 国产熟女完整版中字 | 欧美在线|亚洲| www.色婷婷| 99re在线| 日本丝袜美腿人妻九九| 日本人妻中文字幕精品| 骚女高跟AV在线| 在线观看日韩av不卡| 久久99九九九九6666免费观看软件| 欧美躁死她一区二区| 亚洲AV麻豆Aⅴ无码电影一| 精品国产国产AV| 丁香五月天激情网站| 超碰99re| 九九热超碰97亚洲最新香蕉 | 黄色片一区二区三区四区五区| 精品人妻一二三四区视频| 综合久久欧美| dy888午夜老子影视达达兔| 97色97好| 极品极品色影院| 欧美91在线| 国产久久一区二区| 日本三级中国三级99人妇网站| 天天上日日上日韩精品| 国产诱惑| 亚洲夜色在线| 无码精品久久久天天影视 | 五月婷婷无码| 久久无码一区二区二三区性色| 日韩人妻丝袜美腿中文| 日韩性色b| 精品国产乱码久久久久久口爆网站 | 色男人色天堂东京热| 天天干一干| 新久久AV| 亚州色综合| 亚洲综合贴图91 | 国模91| 天天亚洲综合| 高清在线偷拍自拍视频| 亚洲欧美日韩制服另类| 亚洲AV永久无码精品成人调教| 久久的网站啊啊啊啊啊| 综合啪啪| 亚洲图片日本AⅤ欧美在线| AV色女综合| 91色堂| 国产夜夜艹| 97色色视频| 377p欧洲日本亚洲大胆| 亚洲国产美女久久久久| 粉嫩AV一区二区夜夜| 日韩 女同 综合| 9 7超碰在线免费观看| A V少妇特黄三级| 激情啪啪拍91| 国产毛片久久久久久久| av黄图片在线观看| 啊啊啊好大好深| 亚洲欧美日韩中文久久自慰| 一区二区三区蜜桃成人撸久久东京热 | 丰满人妻一区二区三区| 久久久免费一级黄片| 日韩精品国产一区二区| 免费中文综合精品| 色激情综合网站| 老熟女91视频| 大逼色网站| 男人的天堂三级| 精品无码一区二区人妻久久蜜桃| 99re69综合| 日本精品人妻少妇一区二区| 日韩在线76| 99热婷婷一区二区三| 九九热精彩视频| 色色综合97| 男人天堂综合| 91爱看| 美女AV一区二区| 久久久久9999妇女| 精品国产72| 91成人在线| 色盈盈影院| 中文字幕88av在线| 在线视频五十市| 亚洲视频一二区| 国产九区| 亚州九九九精品视频| 天天影视网色欲色香| 久久九九精品一区二区| 亚洲成人AB| 久久久青青草| 97精品视频| 欧美传媒| 黄片免费看的| 国产午夜激片Av毛片不卡| 嫩草影院在线观看精品| 曰韩成人免费视频| 日本天天色| 观看免费区二区三区二| 东北女人| 青青草无码视频| 97中文字幕一区| 国产精品一区二区三区四区五区| 综合色好色| 在线中文字幕| 国产剧情AV不卡在线观看| 另类专区在线观看| 精品国产少妇高潮视频| 宅男午夜在线视频| 欧洲小说色图视频另类| 怡红院亚洲怡春院av| 色色97爱| 亚洲欧美日韩制服另类| 97在线精品观看视频| 日韩欧美亚洲一区二区三区影院| 东京热免费视频| 亚洲AV无码| 加勒比五月天| 人人操人人摸超碰| 无码137片内射在线影院| 家庭乱伦性爱av| 色婷婷电影网| 久久神马影院| 超碰97极品9| 黄色视频高清无码网站| 色官网色综合| 亚洲中文字幕97久久精品少妇| 91网站18在线| 日韩欧美中文字幕搭讪巨乳美人妻视频| 中文字幕欧美日韩三级| 亚洲成?V人片在线观看福利| 久久人妻视频网| 亚洲精品1区| 天美传媒婬乱在| 久操网无码在线| 97久久精品亚洲| 欧美玖玖爱免费玖玖| 一本久道久久综合狠狠爱一密臀精 | 久久久国产成人一区二区三区在线 | 久久手机好看网站| 久久久91福利姬| 91精品人| 女人爽到高潮潮喷18禁网站| 超碰97玖玖爱| 超碰97人妻自拍| 人妻一区视频| 爱干爱射网啊啊啊| 超碰97伊人| 日韩亚洲中文字幕在线| 亚洲 欧美 另类 综合 偷拍| 97 国产精品| 日本一级婬片试看三分钟| 国产人妻精品久久久一区二区三区| 激情情色五月天| 国产精品日韩在线一区| 美女黄色一级A视频| 9 1超碰九色| 国产精品极品美女视频| 老熟女熟妇| 美女久久久| 激情小说五月天| 伊人国产AV| 日本熟妇人妻中出视频| 亚州色图欧美| 久久av无码| 欧美色图片91| 又大又大又大又粗爽高潮观看| 99热自拍| 欧美,日韩,中文,另类| 人妻日日干| 国产精品一区二区后入| 370p日韩欧美亚洲精品| 欧美色图天堂网m| 欧美片第一页| 超碰97欧美在线 | 五月天伊人| 综合色区偷拍| 啪啪啪大香蕉| 99爱爱| 日韩97视频| 国产操偷| 俺也射| 日本在线视频导航| 亚洲AV永久无码精品成人调教| 午夜久久无码1000合集| 啊啊啊久久久视频| 国产亚洲日本精品在线| 热热色国产一二区AV| 男人的天堂一区三区| 神马久久免费电影观看| 日本岛国黄色网址| 亚洲天天更新| 91狠狠综合久久久久久| 26uuu最新| 色天使大香蕉| 成人av影院在线观看| 蘋果手機免費看成人Av| 男人高清无码一区二区| 亚洲高清在线se| 六月婷婷综合| 夜夜躁狠狠躁日日躁av| 天天综合,91综合永久| 91久久久久久久久18| 97青娱乐超碰久久| 亚洲天堂人妻熟妇视频| 亚洲精品久久久久久| www.夜夜| 婷婷伊人五月| 97 九色| 26uuu国产免费观看| 亚洲欧美日韩不卡人妻| 伊人色综合超碰| 视频黄色国产一级| 日韩电影中文字幕| 色香阁在线| 1级午夜影院费免区| 超碰 国产熟女精品一区| 九九色色| 国产精品久久aV| 色偷偷人人玩人人舔人人操人人摸人人爽| 久久美女福利是上海美女| 蜜臀久久99精品久久久久久-DVD| 国产福利夜| 欧美中出1| 思思热国产高清| 黄色十八禁| 久久,精品一二三| 中文字幕美女91| 久久精品无码熟妇一区二区三区视频导航 | 无码日韩网站| 成·人免费午夜在线观看| 大乔未久88一区| 日本精品一区三区| 精品人妻一区| 97在线视频免费| 亭亭在线资源| 久久久久骚| 日韩精品永久在线观看| 亲子敌伦对白在线播放| 91日日夜夜| 嗯阿好爽好紧| 国产超碰| 色y情视频免费看| 97综合激情| 中文字幕第23区| 精品精品精品| 人妻日日干| 強姦亂倫a| 91在线观看,天天综合| 樱花草社区www中国| 日本三级韩三级99久久| 国产一区二区av综合| 中文AV制服乱伦| 亚洲精品欧洲色| 97精品97久久| 九九久久一区二区三区| 久久伊人大香蕉| 色天使亚洲综合在线观看| 91视频综合网| 亚洲狠狠入| 精品人妻一二三四区视频| 欧美综合第一| 久久婷婷一区二| 在线观看日韩av不卡| 亚洲精品国产专区在线观看| 人妻少妇精品久久久久久久| 丝袜美腿操av| 台湾佬中文娱乐网久久久久久久久久com | 91久久久久免| 韩国黄色片精品久久久| 伦伦成年午夜免费视频| 日韩av三四区| 久久人妻丝袜一区二区三| 国产热RE99久久6国产精品首| 大香蕉久| 在线免费观看日韩一区| 俞拍自拍| 亚州色阁| 日韩少妇丰满亚洲| 丝袜熟女2P| 黄色AV影视| 婷婷五月天成人网| 色色综合网站| 天天天天天干夜夜夜夜夜操| 视频黄色国产一级| 性爱Av免费| 婷婷丁香九月| 强奸乱伦免费网站| 日韩福利综合一区| 精品日韩人妻视频| 一级做a爰片性色毛片久久| 白丝一区| 国产强奸乱伦欧美| 日韩电影在线观看网址| 婷婷伊人五月|