當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
javascript高性能编程笔记(个人自用)
生活随笔
收集整理的這篇文章主要介紹了
javascript高性能编程笔记(个人自用)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
個人讀書筆記,僅用于梳理知識點,摘抄很隨意,若無意搜到的朋友不必細看,不然必凌亂
?
1.大多數(shù)瀏覽器使用單進程處理UI更新和javascript運行,而同一時間只能有一個任務被執(zhí)行,因此<script>標簽的出現(xiàn)使整個頁面因腳本解析,運行被阻塞而出現(xiàn)等待.部分新瀏覽器允許一個<script>標簽正在下載外部資源時,不必阻塞其它<script>標簽.不幸的時,仍然阻塞其它資源(例如圖片)的下載過程. 2.根據(jù)標準,<script>標簽可以放在<head>和<body>標簽中,瀏覽器是遇到<body>標簽后才開始渲染頁面,因此<script>標簽在文檔中最靠后的位置為</body>前,這種做法可以最大限度的降低js對頁面渲染的阻塞. 3.減少<script>總數(shù)也可以改善性能,每個http請求都會產(chǎn)生額外的性能負擔,下載一個100K的文件比下載四個25K的文件要快.(可利用Closure谷歌js,YUI Compressor,Combo Handler雅虎等根據(jù)壓縮合并) 4.如果需向頁面加載大量js,可先加載包含動態(tài)加載js所需的代碼,然后再加載頁面初始化所需的其它js.YUI3核心理念,用一個很小的初始化代碼,下載其余的功能代碼.通用工具有LazyLoad庫(http://github.com/rgrove/lazyload)和LABjs(http://labjs.com),LABjs還可以管理函數(shù)與文件的依賴關系. 5.javascript有4種數(shù)據(jù)存儲位置,Literal values 直接量,Variables 變量,Array items 數(shù)組項,Object members 對象成員,不同的存儲位置可以對代碼整體性能產(chǎn)生重要影響.直接量和局部變量訪問速度非???數(shù)組項和對象成員需要更長時間. 6.局部變量比域外變量快,因為它位于作用域鏈的第一個對象中.變量在作用域鏈中的位置越深,訪問所需的時間就越長.全局變量總是最慢的,因為它們總是位于作用域鏈的最后一環(huán).避免使用with表達式,因為它會增加新作用域鏈在最前端,try-catch中的catch也具有同樣效果.嵌套對象成員會造成重大性能影響,盡量少用. 7.當瀏覽器下載完所有頁面HTML標記,javascript,css,圖片后,它解析文件并創(chuàng)建兩個內部數(shù)據(jù)結構,一顆DOM樹和一顆渲染樹.渲染樹中為每個需要顯示的DOM樹節(jié)點存放至少一個節(jié)點(隱藏DOM除外).渲染樹上的節(jié)點成為"框"或者"盒",符合css模型定義,將頁面元素看作一個具有填充,邊距,邊框和位置的盒.一旦DOM樹和渲染樹構造完畢,瀏覽器就可以顯示(繪制)頁面上的元素了. 8. 當DOM改變影響到元素的幾何屬性(寬和高)等影響到其它元素的幾何屬性和位置.渲染樹上受到影響的部分失效,然后重構(重排)渲染樹.重構完成時,瀏覽器在一個重繪進程中重新繪制屏幕上受影響的部分.而背景顏色等不會影響幾何的屬性變化時,只需要重繪,不需要重排.重繪和重排都是負擔很重的操作. 9.當需要對DOM元素進行多次修改時,可以通過以下三步減少重繪和重排次數(shù),(1)從文檔流中摘除該元素(2)各種改變(3)將元素帶回文檔流,方法有三(1)隱藏元素,進行修改,然后再顯示 (2)使用一個文檔片斷在已存DOM之外創(chuàng)建一個子樹,然后將它拷貝到文檔中 (3)將原始元素拷貝到一個脫離文檔的節(jié)點中,修改副本,然后覆蓋原始元素 10.有些元素的動畫流使用絕對定位,脫離流布局,可以減少DOM的重排 11.利用DOM的冒泡機制,最小化元素事件綁定. 12.js有4種循環(huán)語法for,while,do-while,for-in;因為for-in要迭代搜索實例或者原形的屬性,因此比其它三種語法慢很多.另外盡量保證循環(huán)條件是局部變量,可明顯提升效率. 13.如果循環(huán)次數(shù)過大(如幾十萬次),可考慮使用"達夫設備"優(yōu)化 14.JQuery.each()方法實現(xiàn)了ECMA-262的新方法forEach(),可用于遍歷數(shù)組.不過此基于函數(shù)的迭代會慢于基于循環(huán)的迭代. 15.一般來說,switch總是比if-else更快;當判斷條件較多時,查表法比if-else和switch更快. 16.瀏覽器的調用棧尺寸限制了遞歸算法在js中的應用,如果遇到一個棧溢出錯誤,將方法修改為一個迭代算法或者使用制表法(記憶遞歸)可以避免重復工具. 17. str+="one"+"two" 改寫為 str=str+"one"+"two",會避免產(chǎn)生一個臨時變量. 18.正在表達式處理慢往往是因為匹配失敗過程慢,而不是匹配成功過程慢.最理想的情況是,一個正在表達式的起始字元應當盡可能快速地測試并排除明顯不匹配的位置.減少分支的數(shù)量,縮小它們的范圍,當分支必不可少時,將常用分支放在最前面. 19.如果不需要一個后向引用,可通過(?:...)替代(...). 20.javascript和UI更新共享進程通常被稱作瀏覽器UI線程,此UI線程圍繞著一個簡單的隊列系統(tǒng)工作,任務被保存到隊列中直至進程空閑.一旦空閑,隊列中的下一個任務將被檢索和運行.這些任務不是運行javascript代碼,就是執(zhí)行UI更新,包括重繪和重排版. 21.對于js任務因為復雜性不能在100毫秒或更少時間內完成,這種情況下,理想方法是讓出對UI線程的控制,可使用定時器setTimeout()或setInterval(),等待一段時間后再將js任務添加到UI隊列.定時器與UI線程交互的方式有助于分解長運行腳本成為較短的片斷. 22.定時器代碼只有等創(chuàng)建它的函數(shù)運行完成之后,才有可能被執(zhí)行.如果定時器很小,然后在創(chuàng)建定時器之后又調用了另外一個函數(shù),定時器代碼有可能在創(chuàng)建函數(shù)完成之前加入隊列,比如 var button = document.getElementById("my-button"); button.onclick = function{ ? ? ?oneMethod(); ? ? ?setTimeout(function(){ ? ? ? ? ? document.getElementById("notice").style.color="red"; ??????????},50); ? ? ?anotherMethod(); 如果anotherMethod執(zhí)行時間超過50毫秒,那么定時器代碼將在onclick處理完成之前加入到隊列中 } 23.在任何一種情況下,創(chuàng)建一個定時器造成UI線程暫停,如同它從一個任務切換到下一個任務.因此,定時器代碼復位所有相關的瀏覽器限制,包括長運行腳本時間.此外,調用棧也在定時器代碼中復位為零.這一特效使得定時器成為長運行javascript代碼理想的跨瀏覽器解決方案.(因為瀏覽器會將執(zhí)行時間超過5秒的腳本關閉) 24.如果一個循環(huán)占用太長時間,可以考慮用定時器優(yōu)化,如 for(var i=0,len=items.length;i<len;i++){ ? ? ?protoss(items[i]); } ? ? 如果此處理過程不必同步且數(shù)據(jù)不必按順序處理,則可優(yōu)化為: ? ? ?var todo = items.concat(); ? ? ?setTimeout(function(){ ? ? ?process(todo.shift()); ? ? ?if(todo.length>0){ ? ? ? ? ? setTimeout(arguments.calle,25); ?????}else{ ? ? ?callback(items); ?????} },25) 25. 同理,一個函數(shù)太長,可以考慮是否能夠分解成短時間完成的小函數(shù),如: function saveDocument(id){ ?????openDocument(id); ?????writeText(id); ?????closeDocument(id); ?????updateUI(id); } 優(yōu)化為數(shù)組處理模式: function saveDocument(id){ ? ? ?var tasks = [openDocument,writeText,closeDocument,updateUI]; ? ? ?setTimeout(function(){ ? ? ?var task = tasks.shift(); ? ? ?task(id); ? ? ?if(tasks.length>0){ ? ? ? ? ? setTimeout(arguments.callee,25); ? ? ?} ? ? ?},25); } ?這個版本將每個方法放入任務數(shù)組,然后在每個定時器中調用一個方法. 26. js可連續(xù)運行的最大時間是100毫秒,建議將這個數(shù)字削減一半,不要讓任何js代碼持續(xù)運行超過50毫秒,確保不影響用戶體驗.可用Date對象跟蹤: var start = +new Date(),stop; someLongProcess(); stop = +new Date(); if(stop-start<50){ ? ? ?alert("Just about right."); }else{ ? ? ?alert("Taking too long."); } 應用: function timedProcessArray(items,process,callback){ ? ? ?var todo = items.concat(); ? ? ?setTimeout(function(){ ? ? ?var start = +new Date(); ? ? ?do { ? ? ?process(todo.shift()); ? ? ?}while(todo.length>0 && (+new Date()-start<50)); ? ? ?if(todo.length>0){ ? ? ?setTimeout(arguments.calle,25); ? ? ?}else{ ? ? ?callback(items); ? ? ?} ? ? ?},25); } 27. 過渡的使用定時器會對性能產(chǎn)生負面影響,使用定時器序列,同一時間只有一個定時器存在,只有當這個定時器結束時才能創(chuàng)建一個新的定時器.以這種方式使用定時器不會帶來性能問題. 28.實驗發(fā)現(xiàn),間隔在1秒或以上的定時器,幾乎不影響整個網(wǎng)頁應用的響應,而且200毫秒以下的定時器重復使用,程序會明顯變慢.因此建議限制高頻率重復定時器的數(shù)量,創(chuàng)建單獨重復定時器,每次執(zhí)行多個操作. 29 web workers,作為HTML5的一部分,工人線程AP,已經(jīng)分離成獨立的規(guī)范,在自己的線程中運行js.但工人線程不綁定UI線程,因此訪問瀏覽器資源受到限制.工人線程包含一個navigator對象(只包含四個屬性appName,appVersion,uerAgent和platform),一個location對象(所有屬性只讀),一個self對象指向全局工人線程對象,一個importScripts()方法,使工人線程可以加載外部JavaScript文件,所有ECMAScript對象,XMLHttpRequest構造器,setTimeout()和setInterval()方法,close()方法可以立即停止工人線程. 30.因為工人線程有不同的全局運行環(huán)境,因此需要創(chuàng)建一個完全獨立的js文件, var worker = new Worker("code.js");此代碼一旦執(zhí)行,將為指定文件創(chuàng)建一個新線程和一個新的工人線程運行環(huán)境.此文件被異步下載,至少下載并運行完之后才啟動工人線程. 31.工人線程和網(wǎng)頁代碼通過事件接口進行交互,網(wǎng)頁代碼可通過postMessage()方法向工人線程傳遞數(shù)據(jù),它接收單個參數(shù),即傳遞給工人線程的數(shù)據(jù).此外,在工人線程中還有onmessage事件句柄用于接收信息,例如: ?var worker = new Worker("code.js"); worker.onmessage = function(event){ ? ? ?alert(event.data); } worker.postMessage("Nicholas"); 工人線程從message事件中接收數(shù)據(jù),事件對象具有一個data屬性存放傳入的數(shù)據(jù),工人線程可通過它自己的postMessage()方法將信息返回給頁面. self.onmessage = function(event){ ? ? ?slef.postMessage("hello,"+event.data+"!"); } 消息系統(tǒng)是頁面和工人線程之間唯一的交互途徑,傳遞過去的值或對象都是完全獨立的表述(深拷貝). 32.當工人線程通過importScripts()方法加載外部js時,它接收一個或多個URL參數(shù).工人線程以阻塞方式調用importScripts(),直到所有文件加載完成并執(zhí)行之后,腳本才繼續(xù)運行.由于工人線程在UI線程之外運行,這種阻塞不會影響UI相應, importScripts("file1.js","file2.js"); 33.工人線程適合于那些純數(shù)據(jù),或者與瀏覽器UI沒關系的長運行腳本.任何超過100毫秒的處理,都可以考慮工人線程方案是不是比基于定時器的方案更合適. 34.有五種常用技術用于向服務器請求數(shù)據(jù) ?XMLHttpRequest(XHR) ?Dymamic script tag insertion ?動態(tài)腳本標簽插入 ?iframes ?Comet ?Multipart XHR ?多部分的XHR 35.其中XMLHttpRequest最常用,當使用XHR請求數(shù)據(jù)時,可選擇post或get,如果請求不改變服務器狀態(tài)只是取回數(shù)據(jù),則使用GET.GET請求被緩沖起來,如果你多次提取相同的數(shù)據(jù)可提高性能.只有當URL和參數(shù)長度超過了2048個字符才使用post提取數(shù)據(jù). 36.動態(tài)腳本插入可以跨域,但不能發(fā)送請求頭,只能get,不能post,不能設置超時或重試.實際上,你不需要知道它是否失敗了,必須等待所有數(shù)據(jù)返回后才可以訪問它們.你不能使用裸XML,或者裸JSON,無論什么格式,必須在一個回調函數(shù)之中被組裝起來. var scriptElement = document.createElement('script'); scriptElement.src = 'http://any-domain.com/javascript/lib.js'; document.getElementByTagName_r('head')[0].appendChild(scriptElement); function jsonCallback(jsonString){ ? ? ?var data = ('('+jsonString+')'); } 其中l(wèi)ib.js文件內容為: jsonCallback({"status":1,"colors":["#fff","#000","#ff0000"]}); 37.多部分XHR技術允許只用一個HTTP請求就可以從服務器端獲取多個資源.它通過將資源(css文件,html片斷,js代碼,base64編碼圖片)打包成一個由特定分隔符界定的大字符串,從服務器端發(fā)送到客戶端.js根據(jù)媒體類型和其它"信息頭"解析出每個資源.下面函數(shù)將用于js代碼,css和圖片轉換為瀏覽器可用資源: function handleImageData(data,mimeType){ ? ? ?var img=document.createElement('img'); ? ? ?img.src = 'data:'+mimeType+';base64,'+data; ? ? ?return img; } function handleCss(data){ ? ? ?var style = document.createElement('style'); ? ? ?style.tyle = 'text/css'; ? ? ?var node = document.createTextNode(data); ? ? ?style.appendChild(node); ? ? ?document.getElementByTagName_r('head')[0].appendChild(style); } function handleJavaScript(data){ ? ? ?(data); }由于MXHR響應報文越來越大,有必要在每個資源收到時立刻處理,可以通過監(jiān)聽readyState 3實現(xiàn).每隔15毫秒檢查一次響應報文數(shù)據(jù),數(shù)據(jù)片斷被手機起來直到發(fā)現(xiàn)一個分隔符,然后一切都作為一個完成的資源處理.此技術的最大缺點是此方法獲得的資源不能被瀏覽器緩存. 38.有時你部關心接收數(shù)據(jù),而只要將數(shù)據(jù)發(fā)送給服務器,如記錄日志等.當數(shù)據(jù)只需要發(fā)送給服務器時,有兩種廣泛應用的技術:XHR和燈標.XHR技術同上,而燈標與動態(tài)腳本標簽插入非常類似,js用于創(chuàng)建一個新的Image對象,將src這只為服務器上的一個腳本文件的URL.此URL包含我們打算通過GET格式傳回鍵值對數(shù)據(jù).注意并沒用創(chuàng)建img元素或者將它們插入到DOM中. var url = '/status_tracker.php'; var params = ['step = 2','time =1248027314']; (new Image()).src=url+'?'+params.join('&'); 服務器取得此數(shù)據(jù)并保存下來,而不必向客戶端返回什么,因此沒用實際的圖像顯示,這是將信息發(fā)回服務器的最有效方法.可以監(jiān)聽Image對象的load事件,告訴服務器是否成功接收了數(shù)據(jù).你還可以檢查服務器返回圖片的寬度和高度(如果返回了一張圖片)并用這些數(shù)字通過你服務器的狀態(tài),例如,寬度為1表示"成功",2表示"重試". 如果你不需要為此響應返回數(shù)據(jù),那么你應該發(fā)送一個204 No Content響應代碼,無消息正文.它將組織客戶端繼續(xù)等待. var url = '/status_tracker.php'; var params = ['step = 2','time =1248027314']; var beacon = new Image(); beacon.src = url + '?' + params.join('&'); beacon.onload = function{ ? ? ?if(this.width == 1){ ? ? ??//success ? ? ?} ? ? ?else if (this.width ==2){ ? ? ?//Failure,create another beacon and try again ?????} }; beacon.onerror = function { ? ? ?//Error,wait a bit,then create another beacon and try again } 39.在考慮數(shù)據(jù)傳輸技術時,必須考慮功能集,兼容性,性能,方向.在考慮數(shù)據(jù)格式時,唯一需要比較的就是速度.一般有XML,JSON,HTML,Custom Formatting(自定義格式)四種數(shù)據(jù)格式,總的來說越輕量級越好,最好是json或字符分隔的自定義格式.當創(chuàng)建自定義格式時,最重要的是決定采用何種分隔符,理想情況下,它應當是一個單字符,而且不能存在于你的數(shù)據(jù)之中.JSON-P數(shù)據(jù),可以跨域,但不應涉及敏感數(shù)據(jù). 40.最快的Ajax請求就是不用.有兩種主要方法避免發(fā)出一個不必要的請求.(1)在服務器端,設置HTTP頭,確保返回報文將被緩存在瀏覽器中 (2)在客戶端,于本地緩存已獲取的數(shù)據(jù),不要多次請求同一個數(shù)據(jù). ?前一種技術最容易設置和維護,而第二個給你最大程度的控制. 41.如果你希望Ajax響應報文能夠被瀏覽器所緩存,你必須在發(fā)起請求時使用GET方法.但這還不充分,你必須在響應報文中發(fā)送正確的HTTP頭.Expires頭告訴瀏覽器應當緩存響應報文多長時間.其值是一個日期,當過期之后任何對該URL發(fā)起的請求都不再從緩存中獲得,而要重新訪問服務器.一個Expres頭如下: Expires:Mon,28 Jul 2014 23:30:99 GMT 42.除了依賴瀏覽器處理緩存之外,還可以用手工方法實現(xiàn)它,直接存儲那些從服務器收到的響應報文,可將響應報文存放在一個對象中,以URL為鍵值索引它.這事一個XHR封裝,它首先檢查一個URL此前是否被取用過: var localCache={}; function xhrRequest(url,callback){ ?????//check?the local cache for this URL ? ? ?if(localCache[url]){ ? ? ?callback.success(localCache[url]); ? ? ?return; ?????} ? ? ?//If?this URL wasn't found in the cache,make the request ? ? ?var req = createXhrObject(); ? ? ?req.onerror = function(){ ? ? ? ? ? callback.error(); ?????} ? ? ?req.onreadystatechange = function(){ ? ? ? ? ? if(req.readyState == 4){ ? ? ? ? ? ? ? ?if(req.responseText ===''||req.status == '404'){ ? ? ? ? ? ? ? ?callback.error(); ? ? ? ? ? ? ? ?return; ???????????????} ? ? ? ? ??//Store?the response on the local cache ? ? ? ? ? localCache[url] = req.responseText; ? ? ? ? ? callback.success(req.responseText); ??????????} ?????}; ? ? ?req.open("GET",url,true); ? ? ?req.send(null); } 總的來說,設置一個Expires頭是更好的解決方案.這比較容易,而且其緩存內容可以跨頁面或者跨對話. 43.當在js代碼中執(zhí)行另一段js代碼時,將付出二次評估的代價.二次評估是一項昂貴的操作,eval(),Function(),setTimeout()和setInterval(),盡量避免使用eval和Function,然后在setTimeout和setInterval中傳入函數(shù)代替直接傳入代碼. 44.消除代碼的重復邏輯,可利用延遲加載或條件預加載等消除重復判斷.如: var addHandler = document.body.addEventListener?function(){ 代碼 }:function(){代碼}; 45.位操作運算符運行非常快速,四種位操作符 AND(&),OR(|),XOR(^),NOT(~),在位運算中,數(shù)字被轉換為有符號32位格式,每種操作均直接操作在這個32位數(shù)上實現(xiàn)結果. 46.無論怎樣優(yōu)化javascript代碼,它永遠不會比javascript引擎提供的原生方法更快.因為原生部分都是用低級語言寫的,諸如c++.這意味著這些方法被編譯成機器碼,作為瀏覽器的一部分.經(jīng)驗不足的js開發(fā)者經(jīng)常犯的一個錯誤是在代碼中進行復雜的數(shù)學運算,而沒有使用內置的Math對象中那些性能更好的版本. 47.jquery引擎被認為是最快的css查詢引擎,但它仍比原生的方法慢.原生的querySelector()和querySelectorAll()方法完成它們的任務時,平均只需要基于js的css查詢的10%的時間. 48.減少http請求,合并并壓縮js,css等,可通過Apache Ant的concat任務合并,YUI壓縮器壓縮,google還有更霸道的工具,傳輸?shù)臅r候可以通過gzip再壓縮,可直接在Apache中啟用gzip壓縮功能. 49.預處理js源文件并不會使程序更快,但它允許你在代碼中加入其它語言才有的一些特性,例如用條件體插入一些測試代碼,來衡量你的應用程序的性能. 50.HTML5有離線緩存技術,通過manifest配置要緩存的文件. 51.部署CDN可以極大的減少用戶網(wǎng)絡延遲. 52.工具:性能分析, ? ? ?var Timer={ ? ? ?_data:{}, ? ? ?start:function(key){ ? ? ?Timer._data[key] = new Date(;) ?????}, ? ? ?stop:function(key){ ? ? ?var time=Timer._data[key]; ? ? ?if(time){ ? ? ?Timer._data[key] = new Date()-time; ?????} ?????}, ? ? ?getTime:function(key){ ? ? ?return Timer._data[key]; ?????} ?????}; Timer.start('createElement'); for(i=0;i<count;i++){...} Timer.stop('createElement'); alert('create'+count+'in'+Timer.getTime('createElement'); YUI分析器?http://developer.yahoo.com/yui/profiler/? ? 除了計時功能,還提供了用于函數(shù),對象,和構造器的性能分析接口,還暴擊性能分析的詳細報告.如: var count=10000,i,element; Y.Profiler.start('createElement'); for(i=0;i<count;i++){ ? ? ?element = document.createElement('div'); } Y.Profiler.stop('createElement'); alert('create'+count+'in'+Y.Profiler.getAverage('createElement')+'ms'); 很明顯,它改進了內斂Data和Timer方法,提供額外性能數(shù)據(jù)包含調用次數(shù),平均時間,最小時間,最大時間等. 53.firebug能深入每個被調用函數(shù)的細節(jié),提供高精確性能數(shù)據(jù)和變量查看功能.console.profile()啟動分析器, console.profile("regexTest"); regexTest('foobar','foo'); console.profileEnd(); console.profile("indexOfTest"); indexOfTest('foobar','foo'); console.profileEnd(); 另外console.time()函數(shù)有助于測量循環(huán)和其他分析器不能監(jiān)視的操作: console.time("cache node"); for(var box = document.getElementById("box")),i = 0;i<100;i++){ value = parseFloat(box.style.left)+10; box.style.left = value+"px"; } console.timeEnd("cache node"); ? 在定時器結束之后,時間被輸出到控制帶上 54. page speed最初是google內部開發(fā)的一個工具,后來作為Firebug插件發(fā)布,像Firebug網(wǎng)絡面板一樣提供了關于頁面資源加載的信息.除了加載時間和HTTP狀態(tài),它還顯示javascript解析和運行所花費的時間,指出造成延遲的腳本,并報告那些沒有被使用的函數(shù). ?http://code.google.com/speed/page-speed? 55. Fiddle,一個HTTP調試代理,檢查資源在線傳輸情況,以單位加載瓶頸 56. Yslow 能夠深入視察頁面整體加載和運行過程的性能 57. dynaTrace Ajax Edition Ajax版的dynaTrace ? ?dynaTrace是一個強大的java/.net性能診斷工具,它的開發(fā)人員已經(jīng)發(fā)布了一個"Ajax版"用于策略瀏覽器性能.這個工具免費提供了一個"終端到終端"性能分析器,從網(wǎng)絡和頁面渲染,到腳本運行時間和CPU占用率都能分析.
轉載于:https://www.cnblogs.com/Cohlint/archive/2013/01/14/2860488.html
總結
以上是生活随笔為你收集整理的javascript高性能编程笔记(个人自用)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Maven把一个Application转
- 下一篇: Java基础之字符串String: