真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

java減少代碼體積,java怎么優(yōu)化代碼減少內(nèi)存

java中的壓縮原理是什么?

什么是壓縮文件? 簡單的說,就是經(jīng)過壓縮軟件壓縮的文件叫壓縮文件,壓縮的原理是把文件的二進(jìn)制代碼壓縮,把相鄰的0,1代碼減少,比如有000000,可以把它變成6個(gè)0 的寫法60,來減少該文件的空間。 ■怎么壓縮文件? 首先要安裝壓縮軟件,現(xiàn)在比較流行的是WinRAR「一種高效快速的文件壓縮軟件(中文版)」。 其次是建立一個(gè)壓縮包:選擇你要制作成壓縮包的文件或文件夾,當(dāng)然你也可也多選,方法同資源管理器,也就是按住Ctrl或Shift再選擇文件(文件夾)。 選取完畢之后,就可以單擊工具欄上的“壓縮”按鈕,在這里你可以選擇壓縮格式:RAR和ZIP。 如果你想得到較大的壓縮率,建議選擇RAR格式。 各個(gè)選項(xiàng)選擇好以后,單擊確定按鈕就開始制作壓縮包了,非常方便。有時(shí)候大家會(huì)遇到這個(gè)問題,就是你在一個(gè)論壇里要上傳一些文件壓縮包,壓縮包大小有3M,但是論壇限制會(huì)員上傳大小只有2M,怎么辦呢? 其實(shí)辦法很簡單,就是在你壓縮這個(gè)文件時(shí),分成幾個(gè)帶分卷壓縮包,分卷包大小設(shè)置為2M即可,比如:原來文件名為123.rar(3M),壓縮成分卷包后為123.part1.rar(2M)與123.part2.rar(1M)兩個(gè)文件,這樣你就可以上傳了。 具體方法如下: 1、在要壓縮的文件上點(diǎn)右鍵 2、添加到壓縮文件.... 3、選常規(guī) 4、壓縮方式選最好 5、批定壓縮分卷大小(按字節(jié)計(jì)算),1M = 1024K,1K = 1024字節(jié),填寫數(shù)字即可 當(dāng)你下載了帶有分卷的壓縮包后,如何解壓文件呢? 具體方法如下: 1、把所有的壓縮分卷全部下載完整 2、所有分卷必須在同一個(gè)文件夾內(nèi) 3、然后雙擊解壓第一個(gè)分卷,即可 注:分卷解壓的文件必須是連續(xù)的,若分卷未下載完整,則解壓時(shí)自然會(huì)提示需要下一壓縮分卷

成都創(chuàng)新互聯(lián)長期為千余家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺(tái),與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為鹽湖企業(yè)提供專業(yè)的成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì),鹽湖網(wǎng)站改版等技術(shù)服務(wù)。擁有10余年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。

有沒有減小jar包體積的辦法

通?;卮鹬挥袃煞N,一種是制作一個(gè)可執(zhí)行的 JAR 文件包,然后就可以像.chm 文檔一樣雙擊運(yùn)行了;而另一種是使用 JET 來進(jìn)行 編譯。但是 JET 是要用錢買的,而且據(jù)說 JET 也不是能把所有的 Java 程序都編譯成執(zhí)行文件,性能也要打些折扣。所以,使用制作可執(zhí)行 JAR 文件包的方法就是最佳選擇了,何況它還能保持 Java 的跨平臺(tái)特性。 下面就來看看什么是 JAR 文件包吧: 一. JAR 文件包 JAR 文件就是 Java Archive File,顧名思意,它的應(yīng)用是與 Java 息息相關(guān)的,是 Java 的一種文檔格式。JAR 文件非常類似 ZIP 文件——準(zhǔn)確的說,它就是 ZIP 文件,所以叫它文件包。JAR 文件與 ZIP 文件唯一的區(qū)別就是在 JAR 文件的內(nèi)容中,包含了一個(gè) META-INF/MANIFEST.MF 文件,這個(gè)文件是在生成 JAR 文件的時(shí)候自動(dòng)創(chuàng)建的。舉個(gè)例子,如果我們具有如下目錄結(jié)構(gòu)的一些文件: == `-- test `-- Test.class 把它壓縮成 ZIP 文件 test.zip,則這個(gè) ZIP 文件的內(nèi)部目錄結(jié)構(gòu)為: test.zip `-- test `-- Test.class 如果我們使用 JDK 的 jar 命令把它打成 JAR 文件包 test.jar,則這個(gè) JAR 文件的內(nèi)部目錄結(jié)構(gòu)為: test.jar |-- META-INF |  `-- MANIFEST.MF `-- test `--Test.class 二. 創(chuàng)建可執(zhí)行的 JAR 文件包 制作一個(gè)可執(zhí)行的 JAR 文件包來發(fā)布你的程序是 JAR 文件包最典型的用法。 Java 程序是由若干個(gè) .class 文件組成的。這些 .class 文件必須根據(jù)它們所屬的包不同而分級(jí)分目錄存放;運(yùn)行前需要把所有用到的包的根目錄指定給 CLASSPATH 環(huán)境變量或者 java 命令的 -cp 參數(shù);運(yùn)行時(shí)還要到控制臺(tái)下去使用 java 命令來運(yùn)行,如果需要直接雙擊運(yùn)行必須寫 Windows 的批處理文件 (.bat) 或者 Linux 的 Shell 程序。因此,許多人說,Java 是一種方便開發(fā)者苦了用戶的程序設(shè)計(jì)語言。 其實(shí)不然,如果開發(fā)者能 夠制作一個(gè)可執(zhí)行的 JAR 文件包交給用戶,那么用戶使用起來就方便了。在 Windows 下安裝 JRE (Java Runtime Environment) 的時(shí)候,安裝文件會(huì)將 .jar 文件映射給 javaw.exe 打開。那么,對(duì)于一個(gè)可執(zhí)行的 JAR 文件包,用戶只需要雙擊它就可以運(yùn)行程序了,和閱讀 .chm 文檔一樣方便 (.chm 文檔默認(rèn)是由 hh.exe 打開的)。那么,現(xiàn)在的關(guān)鍵,就是如何來創(chuàng)建這個(gè)可執(zhí)行的 JAR 文件包。 創(chuàng)建可執(zhí)行的 JAR 文件包,需要使用帶 cvfm 參數(shù)的 jar 命令,同樣以上述 test 目錄為例,命令如下: jar cvfm test.jar manifest.mf test 這 里 test.jar 和 manifest.mf 兩個(gè)文件,分別是對(duì)應(yīng)的參數(shù) f 和 m,其重頭戲在 manifest.mf。因?yàn)橐獎(jiǎng)?chuàng)建可執(zhí)行的 JAR 文件包,光靠指定一個(gè) manifest.mf 文件是不夠的,因?yàn)?MANIFEST 是 JAR 文件包的特征,可執(zhí)行的 JAR 文件包和不可執(zhí)行的 JAR 文件包都包含 MANIFEST。關(guān)鍵在于可執(zhí)行 JAR 文件包的 MANIFEST,其內(nèi)容包含了 Main-Class 一項(xiàng)。這在 MANIFEST 中書寫格式如下: Main-Class: 可執(zhí)行主類全名(包含包名) 例如,假設(shè)上例中的 Test.class 是屬于 test 包的,而且是可執(zhí)行的類 (定義了 public static void main(String[]) 方法),那么這個(gè) manifest.mf 可以編輯如下: Main-Class: test.Test ; 這個(gè) manifest.mf 可以放在任何位置,也可以是其它的文件名,只需要有 Main-Class: test.Test 一行,且該行以一個(gè)回車符結(jié)束即可。創(chuàng)建了 manifest.mf 文件之后,我們的目錄結(jié)構(gòu)變?yōu)椋? == |-- test |  `-- Test.class `-- manifest.mf 這時(shí)候,需要到 test 目錄的上級(jí)目錄中去使用 jar 命令來創(chuàng)建 JAR 文件包。也就是在目錄樹中使用“==”表示的那個(gè)目錄中,使用如下命令: jar cvfm test.jar manifest.mf test 之后在“==”目錄中創(chuàng)建了 test.jar,這個(gè) test.jar 就是執(zhí)行的 JAR 文件包。運(yùn)行時(shí)只需要使用 java -jar test.jar 命令即可。 需 要注意的是,創(chuàng)建的 JAR 文件包中需要包含完整的、與 Java 程序的包結(jié)構(gòu)對(duì)應(yīng)的目錄結(jié)構(gòu),就像上例一樣。而 Main-Class 指定的類,也必須是完整的、包含包路徑的類名,如上例的 test.Test;而且在沒有打成 JAR 文件包之前可以使用 java ; 來運(yùn)行這個(gè)類,即在上例中 java test.Test 是可以正確運(yùn)行的 (當(dāng)然要在 CLASSPATH 正確的情況下)。 三. jar 命令詳解 jar 是隨 JDK 安裝的,在 JDK 安裝目錄下的 bin 目錄中,Windows 下文件名為 jar.exe,Linux 下文件名為 jar。它的運(yùn)行需要用到 JDK 安裝目錄下 lib 目錄中的 tools.jar 文件。不過我們除了安裝 JDK 什么也不需要做,因?yàn)?SUN 已經(jīng)幫我們做好了。我們甚至不需要將 tools.jar 放到 CLASSPATH 中。 使用不帶任何的 jar 命令我們可以看到 jar 命令的用法如下: jar {ctxu}[vfm0M] [jar-文件] [manifest-文件] [-C 目錄] 文件名 ... 其中 {ctxu} 是 jar 命令的子命令,每次 jar 命令只能包含 ctxu 中的一個(gè),它們分別表示: -c 創(chuàng)建新的 JAR 文件包 -t 列出 JAR 文件包的內(nèi)容列表 -x 展開 JAR 文件包的指定文件或者所有文件 -u 更新已存在的 JAR 文件包 (添加文件到 JAR 文件包中) [vfm0M] 中的選項(xiàng)可以任選,也可以不選,它們是 jar 命令的選項(xiàng)參數(shù) -v 生成詳細(xì)報(bào)告并打印到標(biāo)準(zhǔn)輸出 -f 指定 JAR 文件名,通常這個(gè)參數(shù)是必須的 -m 指定需要包含的 MANIFEST 清單文件 -0 只存儲(chǔ),不壓縮,這樣產(chǎn)生的 JAR 文件包會(huì)比不用該參數(shù)產(chǎn)生的體積大,但速度更快 -M 不產(chǎn)生所有項(xiàng)的清單(MANIFEST〕文件,此參數(shù)會(huì)忽略 -m 參數(shù) [jar-文件] 即需要生成、查看、更新或者解開的 JAR 文件包,它是 -f 參數(shù)的附屬參數(shù) [manifest-文件] 即 MANIFEST 清單文件,它是 -m 參數(shù)的附屬參數(shù) [-C 目錄] 表示轉(zhuǎn)到指定目錄下去執(zhí)行這個(gè) jar 命令的操作。它相當(dāng)于先使用 cd 命令轉(zhuǎn)該目錄下再執(zhí)行不帶 -C 參數(shù)的 jar 命令,它只能在創(chuàng)建和更新 JAR 文件包的時(shí)候可用。 文件名 ... 指定一個(gè)文件/目錄列表,這些文件/目錄就是要添加到 JAR 文件包中的文件/目錄。如果指定了目錄,那么 jar 命令打包的時(shí)候會(huì)自動(dòng)把該目錄中的所有文件和子目錄打入包中。 下面舉一些例子來說明 jar 命令的用法: 一) jar cf test.jar test 該命令沒有執(zhí)行過程的顯示,執(zhí)行結(jié)果是在當(dāng)前目錄生成了 test.jar 文件。如果當(dāng)前目錄已經(jīng)存在 test.jar,那么該文件將被覆蓋。 二) jar cvf test.jar test 該命令與上例中的結(jié)果相同,但是由于 v 參數(shù)的作用,顯示出了打包過程,如下: 標(biāo)明清單(manifest) 增加:test/(讀入= 0) (寫出= 0)(存儲(chǔ)了 0%) 增加:test/Test.class(讀入= 漆) (寫出= 陸)(壓縮了 一四%) 三) jar cvfM test.jar test 該命令與 二) 結(jié)果類似,但在生成的 test.jar 中沒有包含 META-INF/MANIFEST 文件,打包過程的信息也略有差別: 增加:test/(讀入= 0) (寫出= 0)(存儲(chǔ)了 0%) 增加:test/Test.class(讀入= 漆) (寫出= 陸)(壓縮了 一四%) 四) jar cvfm test.jar manifest.mf test 運(yùn)行結(jié)果與 二) 相似,顯示信息也相同,只是生成 JAR 包中的 META-INF/MANIFEST 內(nèi)容不同,是包含了 manifest.mf 的內(nèi)容 5) jar tf test.jar 在 test.jar 已經(jīng)存在的情況下,可以查看 test.jar 中的內(nèi)容,如對(duì)于 二) 和 三) 生成的 test.jar 分別應(yīng)該此命令,結(jié)果如下; 對(duì)于 二) META-INF/ META-INF/MANIFEST.MF test/ test/Test.class 對(duì)于 三) test/ test/Test.class 陸) jar tvf test.jar 除顯示 5) 中顯示的內(nèi)容外,還包括包內(nèi)文件的詳細(xì)信息,如: 0 Wed Jun 一9 一5:三9:0陸 GMT 二00二 META-INF/ 吧陸 Wed Jun 一9 一5:三9:0陸 GMT 二00二 META-INF/MANIFEST.MF 0 Wed Jun 一9 一5:三三:0四 GMT 二00二 test/ 漆 Wed Jun 一9 一5:三三:0四 GMT 二00二 test/Test.class 漆) jar xf test.jar 解開 test.jar 到當(dāng)前目錄,不顯示任何信息,對(duì)于 二) 生成的 test.jar,解開后的目錄結(jié)構(gòu)如下: == |-- META-INF |  `-- MANIFEST `-- test `--Test.class 吧) jar xvf test.jar 運(yùn)行結(jié)果與 漆) 相同,對(duì)于解壓過程有詳細(xì)信息顯示,如: 創(chuàng)建:META-INF/ 展開:META-INF/MANIFEST.MF 創(chuàng)建:test/ 展開:test/Test.class 9) jar uf test.jar manifest.mf 在 test.jar 中添加了文件 manifest.mf,此使用 jar tf 來查看 test.jar 可以發(fā)現(xiàn) test.jar 中比原來多了一個(gè) manifest。這里順便提一下,如果使用 -m 參數(shù)并指定 manifest.mf 文件,那么 manifest.mf 是作為清單文件 MANIFEST 來使用的,它的內(nèi)容會(huì)被添加到 MANIFEST 中;但是,如果作為一般文件添加到 JAR 文件包中,它跟一般文件無異。 一0) jar uvf test.jar manifest.mf 與 9) 結(jié)果相同,同時(shí)有詳細(xì)信息顯示,如: 增加:manifest.mf(讀入= 一漆) (寫出= 一9)(壓縮了 -一一%) 四. 關(guān)于 JAR 文件包的一些技巧 一) 使用 unzip 來解壓 JAR 文件 在 介紹 JAR 文件的時(shí)候就已經(jīng)說過了,JAR 文件實(shí)際上就是 ZIP 文件,所以可以使用常見的一些解壓 ZIP 文件的工具來解壓 JAR 文件,如 Windows 下的 WinZip、WinRAR 等和 Linux 下的 unzip 等。使用 WinZip 和 WinRAR 等來解壓是因?yàn)樗鼈兘鈮罕容^直觀,方便。而使用 unzip,則是因?yàn)樗鈮簳r(shí)可以使用 -d 參數(shù)指定目標(biāo)目錄。 在解壓一個(gè) JAR 文件的時(shí)候是不能使用 jar 的 -C 參數(shù)來指定解壓的目標(biāo)的,因?yàn)?-C 參數(shù)只在創(chuàng)建或者更新包的時(shí)候可用。那么需要將文件解壓到某個(gè)指定目錄下的時(shí)候就需要先將這具 JAR 文件拷貝到目標(biāo)目錄下,再進(jìn)行解壓,比較麻煩。如果使用 unzip,就不需要這么麻煩了,只需要指定一個(gè) -d 參數(shù)即可。如: unzip test.jar -d dest/ 二) 使用 WinZip 或者 WinRAR 等工具創(chuàng)建 JAR 文件 上 面提到 JAR 文件就是包含了 META-INF/MANIFEST 的 ZIP 文件,所以,只需要使用 WinZip、WinRAR 等工具創(chuàng)建所需要 ZIP 壓縮包,再往這個(gè) ZIP 壓縮包中添加一個(gè)包含 MANIFEST 文件的 META-INF 目錄即可。對(duì)于使用 jar 命令的 -m 參數(shù)指定清單文件的情況,只需要將這個(gè) MANIFEST 按需要修改即可。 三) 使用 jar 命令創(chuàng)建 ZIP 文件 有 些 Linux 下提供了 unzip 命令,但沒有 zip 命令,所以需要可以對(duì) ZIP 文件進(jìn)行解壓,即不能創(chuàng)建 ZIP 文件。如要?jiǎng)?chuàng)建一個(gè) ZIP 文件,使用帶 -M 參數(shù)的 jar 命令即可,因?yàn)?-M 參數(shù)表示制作 JAR 包的時(shí)候不添加 MANIFEST 清單,那么只需要在指定目標(biāo) JAR 文件的地方將 .jar 擴(kuò)展名改為 .zip 擴(kuò)展名,創(chuàng)建的就是一個(gè)不折不扣的 ZIP 文件了,如將上一節(jié)的第 三) 個(gè)例子略作改動(dòng): jar cvfM test.zip tes

java編的程序?yàn)槭裁大w積非常小?

手機(jī)平臺(tái)用的java,是java的精簡版本,一般稱作j2me,而樓主所說的java,是j2se或者j2ee。j2me的功能非常小,僅僅支持最基本的java函數(shù),。java文件打包通過sun公司提供的wtk打包,將源程序放在src文件夾中,資源文件放于res文件夾中,然后生成就可以了。源程序可以到下載。

樓主如果不想做手機(jī)游戲的話,就可以不用考慮為自己的手機(jī)上增加自己寫的東西了,因?yàn)閖2me主要是用來開發(fā)手機(jī)游戲,想從事此項(xiàng)目的開發(fā),必須得經(jīng)過專業(yè)的培訓(xùn)才行,不是一兩句話能說的明白的,樓主可以到網(wǎng)上搜尋j2me相關(guān)的信息看看

c#和java哪個(gè)更好點(diǎn)。

很多人說C#是微軟用來和Java抗衡的武器,因?yàn)槎咴诤艽蟪潭壬嫌兄@人的相似

,盡管如此,兩者不同的地方也很多,所謂“于細(xì)微處見差異”。那么兩者的相似和區(qū)

別都在什么地方呢?我們從今天開始,會(huì)從各個(gè)角度來對(duì)比C#和Java的特點(diǎn),希望能對(duì)

正在學(xué)習(xí)、使用C#的朋友有所幫助。

1、C#和.NET平臺(tái)的概貌

2000年6月,微軟發(fā)布C#語言和.NET平臺(tái)。C#語言是一種強(qiáng)類型的,面向?qū)ο蟮恼Z言

,它具有語法簡單、表達(dá)力強(qiáng)的特點(diǎn),而.NET平臺(tái)則是構(gòu)成微軟的“.NET計(jì)劃”的基石

.NET平臺(tái)的核心包括兩方面,一方面就是著名的通用語言運(yùn)行機(jī)(Common Language

Runtime),雖然這個(gè)名詞起得晦澀了點(diǎn),不過大家可以拿它和Java的虛擬機(jī)來作比較,

二者完成的任務(wù)大致相同;另一方面就是一大堆通用函數(shù)庫,這些庫函數(shù)可以被多種語

言調(diào)用,并且通過編譯都產(chǎn)生一種共同的中間語言(Intermediate Language),這種語

言也可以拿Java的字節(jié)碼來類比,雖然完成的方式有些不一樣。

2、C#和Java

下面簡單地把C#和Java的相似處列出來,雖然在這里我們重點(diǎn)討論的是C#和Java的

不同點(diǎn),但是了解一下二者的相同之處也是很有必要的。

二者都編譯成跨平臺(tái)的、跨語言的代碼,并且代碼只能在一個(gè)受控制的環(huán)境中運(yùn)行

自動(dòng)回收垃圾內(nèi)存,并且消除了指針(在C#中可以使用指針,不過必須注明unsafe

關(guān)鍵字)

都不需要頭文件,所有的代碼都被“包(package)”限制在某個(gè)范圍內(nèi),并且因?yàn)闆]

有頭文件,所以消除了類定義的循環(huán)依賴

所有的類都是從對(duì)象派生出來,并且必須使用New關(guān)鍵字分配內(nèi)存

用對(duì)象加鎖的方式來支持多線程

都具有接口(interface)的概念

內(nèi)部類

繼承類的時(shí)候不會(huì)以某種特定的訪問權(quán)限來繼承;

沒有全局函數(shù)或者常量,一切必須屬于類;

數(shù)組或者字符串都自帶長度計(jì)算和邊界檢查;

只使用“.”操作符,沒有“-”和“::”;

“null”、“boolean”和“bool”成為了關(guān)鍵字;

任何變量均在使用前進(jìn)行初始化;

不能使用整數(shù)來返回到if條件語句中,必須使用布爾值;

“Try”模塊后可以有“finally” ;

3. 屬性(Property)

屬性的概念對(duì)大家來說應(yīng)該是很熟悉的,類成員函數(shù)可以自由地訪問本類中的任何

屬性成員。不過若要從一個(gè)類中去訪問另一個(gè)類中的屬性,那就比較麻煩了,所以很多

時(shí)候我們使用Getxxx和Setxxx方法,這樣看起來顯得極不自然,比如用Java或者C++,代

碼是這樣的:

foo.setSize (getSize () + 1);

label.getFont().setBold (true);

但是,在C#中,這樣的方法被“屬性化”了。同樣的代碼,在C#就變成了:

foo.size++;

label.font.bold = true;

可以看出來,C#顯然更容易閱讀和理解。我們從這個(gè)“屬性方法”的子程序代碼中

,也可以看到類似情況:

Java/C++:

public int getSize()

{

return size;

}

public void setSize (int value)

{

size = value;

}

C#:

public int Size

{

 get{return size;}

 set{size = value;}

}

為了區(qū)分這種屬性化的方法和類的屬性成員,在C#中把屬性成員稱作“域(field)”

,而“屬性”則成為這種“屬性化的方法”專用的名詞。順便說一句,其實(shí)這樣的屬性

化方法在VB和DELPHI中是經(jīng)常碰到的,在VB中它也就叫屬性。

另外,在C#中Get和Set必須成對(duì)出現(xiàn),一種屬性不能只有Get而沒有Set(在Java和

C++中就可以只有Get或者只有Set),C#中這樣做的好處在于便于維護(hù),假如要對(duì)某種屬

性進(jìn)行修改,就會(huì)同時(shí)注意Get和Set方法,同時(shí)修改,不會(huì)改了這個(gè)忘了那個(gè)。

4、對(duì)象索引機(jī)制(Indexer)

C#中引入了對(duì)象索引機(jī)制。說得明白點(diǎn),對(duì)象索引其實(shí)就是對(duì)象數(shù)組。這里和上一

節(jié)中的屬性聯(lián)系起來講一下,屬性需要隱藏Get和Set方法,而在索引機(jī)制中,各個(gè)對(duì)象

的Get或者Set方法是暴露出來的。比如下面的例子就比較清楚地說明了這一點(diǎn)。

public class Skyscraper

{

 Story[] stories;

 public Story this [int index] {

get {

 return stories [index];

}

set {

 if (value != null) {

stories [index] = value;

 }

}

 }

...

}

5. 指代(Delegate)

指代這個(gè)玩意很特別,它有點(diǎn)象指針,但又不完全是,不過大家還是可以把它理解

為一種類型安全的、面向?qū)ο蟮闹羔?。(什么是類型安全和面向?qū)ο缶筒挥弥v了吧?)

順便提一句,有很多書上把Delegate翻譯成代理,我覺得這樣翻不夠確切,翻譯成“指

代”更恰當(dāng)些,道理上吻合,并且還符合它的本來意思——微軟本來就是用Delegate來

“取代指針”,所以叫“指代”,呵呵。

說起指代,也許至今Sun還會(huì)對(duì)它憤憤不已,為什么呢?因?yàn)樵赟un的標(biāo)準(zhǔn)Java中是

沒有這個(gè)東西的,它是微軟99年發(fā)布的MSVJ++6添加的“新特性”。為此,兩家公司吵得

不亦樂乎,并且還專門在網(wǎng)上寫了大量文章互相攻擊,有興趣的朋友可以去看看(只有

英文版)。

話歸正傳,指代有什么特點(diǎn)呢?一個(gè)明顯的特點(diǎn)就是它具有了指針的行為,就好象

從Java又倒回到了C++。在C#中,指代完成的功能大概和C++里面的指針,以及Java中的

接口相當(dāng)。但是,指代比起C++的“正宗指針”來又要高明一些,因?yàn)樗梢酝瑫r(shí)擁有多

個(gè)方法,相當(dāng)于C++里面的指針能同時(shí)指向多個(gè)函數(shù),并且是類型安全的,這一點(diǎn)體現(xiàn)了

它的“對(duì)象”特性;而比起Java的接口來,指代高明的地方在于它能可以不經(jīng)過內(nèi)部類

就調(diào)用函數(shù),或者用少量代碼就能調(diào)用多種函數(shù),這一點(diǎn)體現(xiàn)了它的“指針”特性。呵

呵,很有“波粒二象性”的味道吧?指代最重要的應(yīng)用在于對(duì)于事件的處理,下一節(jié)我

們將重點(diǎn)介紹。

6、事件(Event)

C#對(duì)事件是直接支持的(這個(gè)特點(diǎn)也是MSVJ所具有的)。當(dāng)前很多主流程序語言處

理事件的方式各不相同,Delphi采用的是函數(shù)指針(這在Delphi中的術(shù)語是“closure”

)、Java用改編類來實(shí)現(xiàn)、VC用WindowsAPI的消息系統(tǒng),而C#則直接使用delegate和ev

ent關(guān)鍵字來解決這個(gè)問題。下面讓我們來看一個(gè)例子,例子中會(huì)給大家舉出聲明、調(diào)用

和處理事件的全過程。

//首先是指代的聲明,它定義了喚醒某個(gè)函數(shù)的事件信號(hào)

public delegate void ScoreChangeEventHandler (int newScore, ref bool cancel)

;

//定義一個(gè)產(chǎn)生事件的類

public class Game

{

 // 注意這里使用了event關(guān)鍵字

 public event ScoreChangeEventHandler ScoreChange;

int score;

// Score 屬性

public int Score

{

 get {

return score;

 }

 set {

if (score != value)

{

 bool cancel = false;

 ScoreChange (value, ref cancel);

 if (! cancel)

 score = value;

}

}

}

// 處理事件的類

public class Referee

{

 public Referee (Game game)

 {

// 裁判負(fù)責(zé)調(diào)整比賽中的分?jǐn)?shù)變化

game.ScoreChange += new ScoreChangeEventHandler (game_ScoreChange);

 }

 // 注意這里的函數(shù)是怎樣和ScoreChangeEventHandler的信號(hào)對(duì)上號(hào)的

 private void game_ScoreChange (int newScore, ref bool cancel)

 {

if (newScore 100)

 System.Console.WriteLine ("Good Score");

else

{

 cancel = true;

 System.Console.WriteLine ("No Score can be that high!");

}

 }

}

// 主函數(shù)類,用于測(cè)試上述特性

public class GameTest

{

 public static void Main ()

 {

Game game = new Game ();

Referee referee = new Referee (game);

game.Score = 70;

game.Score = 110;

 }

}

在主函數(shù)中,我們創(chuàng)建了一個(gè)game對(duì)象和一個(gè)裁判對(duì)象,然后我們通過改變比賽分

數(shù),來觀察裁判對(duì)此會(huì)有什么響應(yīng)。

請(qǐng)注意,我們的這個(gè)系統(tǒng)中,Game對(duì)象是感覺不到裁判對(duì)象的存在的,Game對(duì)象在

這里只負(fù)責(zé)產(chǎn)生事件,至于有誰會(huì)來傾聽這個(gè)事件,并為之作出反應(yīng),Game對(duì)象是不作

任何表態(tài)的。

我們注意到,在裁判類的Referee函數(shù)中,Game.ScoreChange后面使用了+=和-=操作

符,這是什么意思呢?回到我們定義ScoreChange的地方,可以發(fā)現(xiàn)ScoreChange是用ev

ent關(guān)鍵字修飾的,那么這里的意思就很明白了:ScoreChange是一個(gè)事件,而事件被觸

發(fā)后需要相應(yīng)的事件處理機(jī)制,+=/-=就是為這個(gè)事件增加/移除相對(duì)應(yīng)的事件處理程序

,而且,并不是一個(gè)事件只能對(duì)應(yīng)一個(gè)處理程序,我們還可以用這兩個(gè)操作符為同一事

件增加/移除數(shù)個(gè)事件處理程序。怎么樣?很方便吧!

在實(shí)際應(yīng)用中,和我們上面講的(競(jìng)賽-裁判)機(jī)制很相近的系統(tǒng)就是圖形用戶界面

系統(tǒng)了。Game對(duì)象可以看作是圖形界面上的小零件,而得分事件就相當(dāng)于用戶輸入事件

,而裁判就相當(dāng)于相應(yīng)的應(yīng)用程序,用于處理用戶輸入。

指代機(jī)制的首次亮相是在MSVJ里,它是由Anders Hejlsberg發(fā)明的,現(xiàn)在又用到了

C#中。指代用在Java語言中的后果,則直接導(dǎo)致了微軟和Sun之間對(duì)類和指針的關(guān)系產(chǎn)生

了大量的爭(zhēng)論和探討。有意思的是,Java的發(fā)明者James Gosling非常幽默地稱呼指代的

發(fā)明者Anders Hejlsberg為“‘函數(shù)指針’先生”,因?yàn)锳nders Hejlsberg總是想方設(shè)

法地把指針變相地往各種語言中放;不過有人在看了Java中大量地使用了各種類后,也

戲稱Java的發(fā)明者James Gosling為“‘全都是類’先生”,真是其中滋味,盡在不言中

啊。

在MyEcjava里java代碼太長,在代碼里寫些什么關(guān)鍵詞可把代碼收起來?

這個(gè)。。。java現(xiàn)在還沒那么先進(jìn),你把一行拆成兩行不行嗎

還是那句話,沒有什么關(guān)鍵詞可以使當(dāng)前語句自動(dòng)收縮,那是IDE干的活。。。

如果你怕別人無意修改代碼,那么多寫幾個(gè)類,用繼承和重構(gòu)的方法來減少一個(gè)類里的代碼量

如何優(yōu)化JAVA代碼及提高執(zhí)行效率

可供程序利用的資源(內(nèi)存、CPU時(shí)間、網(wǎng)絡(luò)帶寬等)是有限的,優(yōu)化的目的就是讓程序用盡可能少的資源完成預(yù)定的任務(wù)。優(yōu)化通常包含兩方面的內(nèi)容:減小代碼的體積,提高代碼的運(yùn)行效率。本文討論的主要是如何提高代碼的效率。

在Java程序中,性能問題的大部分原因并不在于Java語言,而是在于程序本身。養(yǎng)成好的代碼編寫習(xí)慣非常重要,比如正確地、巧妙地運(yùn)用java.lang.String類和java.util.Vector類,它能夠顯著地提高程序的性能。下面我們就來具體地分析一下這方面的問題。

1、 盡量指定類的final修飾符帶有final修飾符的類是不可派生的。在Java核心API中,有許多應(yīng)用final的例子,例如java.lang.String。為String類指定final防止了人們覆蓋length()方法。另外,如果指定一個(gè)類為final,則該類所有的方法都是final。Java編譯器會(huì)尋找機(jī)會(huì)內(nèi)聯(lián)(inline)所有的final方法(這和具體的編譯器實(shí)現(xiàn)有關(guān))。此舉能夠使性能平均提高50%

。

2、 盡量重用對(duì)象。特別是String 對(duì)象的使用中,出現(xiàn)字符串連接情況時(shí)應(yīng)用StringBuffer 代替。由于系統(tǒng)不僅要花時(shí)間生成對(duì)象,以后可能還需花時(shí)間對(duì)這些對(duì)象進(jìn)行垃圾回收和處理。因此,生成過多的對(duì)象將會(huì)給程序的性能帶來很大的影響。

3、 盡量使用局部變量,調(diào)用方法時(shí)傳遞的參數(shù)以及在調(diào)用中創(chuàng)建的臨時(shí)變量都保存在棧(Stack)中,速度較快。其他變量,如靜態(tài)變量、實(shí)例變量等,都在堆(Heap)中創(chuàng)建,速度較慢。另外,依賴于具體的編譯器/JVM,局部變量還可能得到進(jìn)一步優(yōu)化。請(qǐng)參見《盡可能使用堆棧變量》。

4、 不要重復(fù)初始化變量 默認(rèn)情況下,調(diào)用類的構(gòu)造函數(shù)時(shí),

Java會(huì)把變量初始化成確定的值:所有的對(duì)象被設(shè)置成null,整數(shù)變量(byte、short、int、long)設(shè)置成0,float和double變量設(shè)置成0.0,邏輯值設(shè)置成false。當(dāng)一個(gè)類從另一個(gè)類派生時(shí),這一點(diǎn)尤其應(yīng)該注意,因?yàn)橛胣ew關(guān)鍵詞創(chuàng)建一個(gè)對(duì)象時(shí),構(gòu)造函數(shù)鏈中的所有構(gòu)造函數(shù)都會(huì)被自動(dòng)調(diào)用。

5、 在JAVA + ORACLE 的應(yīng)用系統(tǒng)開發(fā)中,java中內(nèi)嵌的SQL語句盡量使用大寫的形式,以減輕ORACLE解析器的解析負(fù)擔(dān)。

6、 Java 編程過程中,進(jìn)行數(shù)據(jù)庫連接、I/O流操作時(shí)務(wù)必小心,在使用完畢后,即使關(guān)閉以釋放資源。因?yàn)閷?duì)這些大對(duì)象的操作會(huì)造成系統(tǒng)大的開銷,稍有不慎,會(huì)導(dǎo)致嚴(yán)重的后果。

7、 由于JVM的有其自身的GC機(jī)制,不需要程序開發(fā)者的過多考慮,從一定程度上減輕了開發(fā)者負(fù)擔(dān),但同時(shí)也遺漏了隱患,過分的創(chuàng)建對(duì)象會(huì)消耗系統(tǒng)的大量內(nèi)存,嚴(yán)重時(shí)會(huì)導(dǎo)致內(nèi)存泄露,因此,保證過期對(duì)象的及時(shí)回收具有重要意義。JVM回收垃圾的條件是:對(duì)象不在被引用;然而,JVM的GC并非十分的機(jī)智,即使對(duì)象滿足了垃圾回收的條件也不一定會(huì)被立即回收。所以,建議我們?cè)趯?duì)象使用完畢,應(yīng)手動(dòng)置成null。

8、 在使用同步機(jī)制時(shí),應(yīng)盡量使用方法同步代替代碼塊同步。

9、 盡量減少對(duì)變量的重復(fù)計(jì)算

例如:for(int i = 0;i list.size; i ++) {

}

應(yīng)替換為:

for(int i = 0,int len = list.size();i len; i ++) {

}

10、盡量采用lazy loading 的策略,即在需要的時(shí)候才開始創(chuàng)建。

例如: String str = “aaa”;

if(i == 1) {

list.add(str);

}

應(yīng)替換為:

if(i == 1) {

String str = “aaa”;

list.add(str);

}

11、慎用異常

異常對(duì)性能不利。拋出異常首先要?jiǎng)?chuàng)建一個(gè)新的對(duì)象。Throwable接口的構(gòu)造函數(shù)調(diào)用名為fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法檢查堆棧,收集調(diào)用跟蹤信息。只要有異常被拋出,VM就必須調(diào)整調(diào)用堆棧,因?yàn)樵谔幚磉^程中創(chuàng)建了一個(gè)新的對(duì)象。異常只能用于錯(cuò)誤處理,不應(yīng)該用來控制程序流程。

12、不要在循環(huán)中使用:

Try {

} catch() {

}

應(yīng)把其放置在最外層。

13、StringBuffer 的使用:

StringBuffer表示了可變的、可寫的字符串。

有三個(gè)構(gòu)造方法 :

StringBuffer (); //默認(rèn)分配16個(gè)字符的空間

StringBuffer (int size); //分配size個(gè)字符的空間

StringBuffer (String str); //分配16個(gè)字符+str.length()個(gè)字符空間

你可以通過StringBuffer的構(gòu)造函數(shù)來設(shè)定它的初始化容量,這樣可以明顯地提升性能。這里提到的構(gòu)造函數(shù)是StringBuffer(int

length),length參數(shù)表示當(dāng)前的StringBuffer能保持的字符數(shù)量。你也可以使用ensureCapacity(int

minimumcapacity)方法在StringBuffer對(duì)象創(chuàng)建之后設(shè)置它的容量。首先我們看看StringBuffer的缺省行為,然后再找出一條更好的提升性能的途徑。

StringBuffer在內(nèi)部維護(hù)一個(gè)字符數(shù)組,當(dāng)你使用缺省的構(gòu)造函數(shù)來創(chuàng)建StringBuffer對(duì)象的時(shí)候,因?yàn)闆]有設(shè)置初始化字符長度,StringBuffer的容量被初始化為16個(gè)字符,也就是說缺省容量就是16個(gè)字符。當(dāng)StringBuffer達(dá)到最大容量的時(shí)候,它會(huì)將自身容量增加到當(dāng)前的2倍再加2,也就是(2*舊值+2)。如果你使用缺省值,初始化之后接著往里面追加字符,在你追加到第16個(gè)字符的時(shí)候它會(huì)將容量增加到34(2*16+2),當(dāng)追加到34個(gè)字符的時(shí)候就會(huì)將容量增加到70(2*34+2)。無論何事只要StringBuffer到達(dá)它的最大容量它就不得不創(chuàng)建一個(gè)新的字符數(shù)組然后重新將舊字符和新字符都拷貝一遍――這也太昂貴了點(diǎn)。所以總是給StringBuffer設(shè)置一個(gè)合理的初始化容量值是錯(cuò)不了的,這樣會(huì)帶來立竿見影的性能增益。

StringBuffer初始化過程的調(diào)整的作用由此可見一斑。所以,使用一個(gè)合適的容量值來初始化StringBuffer永遠(yuǎn)都是一個(gè)最佳的建議。

14、合理的使用Java類 java.util.Vector。

簡單地說,一個(gè)Vector就是一個(gè)java.lang.Object實(shí)例的數(shù)組。Vector與數(shù)組相似,它的元素可以通過整數(shù)形式的索引訪問。但是,Vector類型的對(duì)象在創(chuàng)建之后,對(duì)象的大小能夠根據(jù)元素的增加或者刪除而擴(kuò)展、縮小。請(qǐng)考慮下面這個(gè)向Vector加入元素的例子:

Object obj = new Object();

Vector v = new Vector(100000);

for(int I=0;

I100000; I++) { v.add(0,obj); }

除非有絕對(duì)充足的理由要求每次都把新元素插入到Vector的前面,否則上面的代碼對(duì)性能不利。在默認(rèn)構(gòu)造函數(shù)中,Vector的初始存儲(chǔ)能力是10個(gè)元素,如果新元素加入時(shí)存儲(chǔ)能力不足,則以后存儲(chǔ)能力每次加倍。Vector類就象StringBuffer類一樣,每次擴(kuò)展存儲(chǔ)能力時(shí),所有現(xiàn)有的元素都要復(fù)制到新的存儲(chǔ)空間之中。下面的代碼片段要比前面的例子快幾個(gè)數(shù)量級(jí):

Object obj = new Object();

Vector v = new Vector(100000);

for(int I=0; I100000; I++) { v.add(obj); }

同樣的規(guī)則也適用于Vector類的remove()方法。由于Vector中各個(gè)元素之間不能含有“空隙”,刪除除最后一個(gè)元素之外的任意其他元素都導(dǎo)致被刪除元素之后的元素向前移動(dòng)。也就是說,從Vector刪除最后一個(gè)元素要比刪除第一個(gè)元素“開銷”低好幾倍。

假設(shè)要從前面的Vector刪除所有元素,我們可以使用這種代碼:

for(int I=0; I100000; I++)

{

 v.remove(0);

}

但是,與下面的代碼相比,前面的代碼要慢幾個(gè)數(shù)量級(jí):

for(int I=0; I100000; I++)

{

 v.remove(v.size()-1);

}

從Vector類型的對(duì)象v刪除所有元素的最好方法是:

v.removeAllElements();

假設(shè)Vector類型的對(duì)象v包含字符串“Hello”??紤]下面的代碼,它要從這個(gè)Vector中刪除“Hello”字符串:

String s = "Hello";

int i = v.indexOf(s);

if(I != -1) v.remove(s);

這些代碼看起來沒什么錯(cuò)誤,但它同樣對(duì)性能不利。在這段代碼中,indexOf()方法對(duì)v進(jìn)行順序搜索尋找字符串“Hello”,remove(s)方法也要進(jìn)行同樣的順序搜索。改進(jìn)之后的版本是:

String s = "Hello";

int i = v.indexOf(s);

if(I != -1) v.remove(i);

這個(gè)版本中我們直接在remove()方法中給出待刪除元素的精確索引位置,從而避免了第二次搜索。一個(gè)更好的版本是:

String s = "Hello"; v.remove(s);

最后,我們?cè)賮砜匆粋€(gè)有關(guān)Vector類的代碼片段:

for(int I=0; I++;I v.length)

如果v包含100,000個(gè)元素,這個(gè)代碼片段將調(diào)用v.size()方法100,000次。雖然size方法是一個(gè)簡單的方法,但它仍舊需要一次方法調(diào)用的開銷,至少JVM需要為它配置以及清除堆棧環(huán)境。在這里,for循環(huán)內(nèi)部的代碼不會(huì)以任何方式修改Vector類型對(duì)象v的大小,因此上面的代碼最好改寫成下面這種形式:

int size = v.size(); for(int I=0; I++;Isize)

雖然這是一個(gè)簡單的改動(dòng),但它仍舊贏得了性能。畢竟,每一個(gè)CPU周期都是寶貴的。

15、當(dāng)復(fù)制大量數(shù)據(jù)時(shí),使用System.arraycopy()命令。

16、代碼重構(gòu):增強(qiáng)代碼的可讀性。

例如:

public class ShopCart {

private List carts ;

public void add (Object item) {

if(carts == null) {

carts = new ArrayList();

}

crts.add(item);

}

public void remove(Object item) {

if(carts. contains(item)) {

carts.remove(item);

}

}

public List getCarts() {

//返回只讀列表

return Collections.unmodifiableList(carts);

}

//不推薦這種方式

//this.getCarts().add(item);

}

17、不用new關(guān)鍵詞創(chuàng)建類的實(shí)例

用new關(guān)鍵詞創(chuàng)建類的實(shí)例時(shí),構(gòu)造函數(shù)鏈中的所有構(gòu)造函數(shù)都會(huì)被自動(dòng)調(diào)用。但如果一個(gè)對(duì)象實(shí)現(xiàn)了Cloneable接口,我們可以調(diào)用它的clone()方法。clone()方法不會(huì)調(diào)用任何類構(gòu)造函數(shù)。

在使用設(shè)計(jì)模式(Design Pattern)的場(chǎng)合,如果用Factory模式創(chuàng)建對(duì)象,則改用clone()方法創(chuàng)建新的對(duì)象實(shí)例非常簡單。例如,下面是Factory模式的一個(gè)典型實(shí)現(xiàn):

public static Credit getNewCredit() {

return new Credit();

}

改進(jìn)后的代碼使用clone()方法,如下所示:

private static Credit BaseCredit = new Credit();

public static Credit getNewCredit() {

return (Credit) BaseCredit.clone();

}

上面的思路對(duì)于數(shù)組處理同樣很有用。

18、乘法和除法

考慮下面的代碼:

for (val = 0; val 100000; val +=5) {

alterX = val * 8; myResult = val * 2;

}

用移位操作替代乘法操作可以極大地提高性能。下面是修改后的代碼:

for (val = 0; val 100000; val += 5) {

alterX = val 3; myResult = val 1;

}

修改后的代碼不再做乘以8的操作,而是改用等價(jià)的左移3位操作,每左移1位相當(dāng)于乘以2。相應(yīng)地,右移1位操作相當(dāng)于除以2。值得一提的是,雖然移位操作速度快,但可能使代碼比較難于理解,所以最好加上一些注釋。

19、在JSP頁面中關(guān)閉無用的會(huì)話。

一個(gè)常見的誤解是以為session在有客戶端訪問時(shí)就被創(chuàng)建,然而事實(shí)是直到某server端程序調(diào)用HttpServletRequest.getSession(true)這樣的語句時(shí)才被創(chuàng)建,注意如果JSP沒有顯示的使用 %@pagesession="false"% 關(guān)閉session,則JSP文件在編譯成Servlet時(shí)將會(huì)自動(dòng)加上這樣一條語句HttpSession

session = HttpServletRequest.getSession(true);這也是JSP中隱含的session對(duì)象的來歷。由于session會(huì)消耗內(nèi)存資源,因此,如果不打算使用session,應(yīng)該在所有的JSP中關(guān)閉它。

對(duì)于那些無需跟蹤會(huì)話狀態(tài)的頁面,關(guān)閉自動(dòng)創(chuàng)建的會(huì)話可以節(jié)省一些資源。使用如下page指令:%@ page session="false"%

20、JDBC與I/O

如果應(yīng)用程序需要訪問一個(gè)規(guī)模很大的數(shù)據(jù)集,則應(yīng)當(dāng)考慮使用塊提取方式。默認(rèn)情況下,JDBC每次提取32行數(shù)據(jù)。舉例來說,假設(shè)我們要遍歷一個(gè)5000行的記錄集,JDBC必須調(diào)用數(shù)據(jù)庫157次才能提取到全部數(shù)據(jù)。如果把塊大小改成512,則調(diào)用數(shù)據(jù)庫的次數(shù)將減少到10次。

[p][/p]21、Servlet與內(nèi)存使用

許多開發(fā)者隨意地把大量信息保存到用戶會(huì)話之中。一些時(shí)候,保存在會(huì)話中的對(duì)象沒有及時(shí)地被垃圾回收機(jī)制回收。從性能上看,典型的癥狀是用戶感到系統(tǒng)周期性地變慢,卻又不能把原因歸于任何一個(gè)具體的組件。如果監(jiān)視JVM的堆空間,它的表現(xiàn)是內(nèi)存占用不正常地大起大落。

解決這類內(nèi)存問題主要有二種辦法。第一種辦法是,在所有作用范圍為會(huì)話的Bean中實(shí)現(xiàn)HttpSessionBindingListener接口。這樣,只要實(shí)現(xiàn)valueUnbound()方法,就可以顯式地釋放Bean使用的資源。另外一種辦法就是盡快地把會(huì)話作廢。大多數(shù)應(yīng)用服務(wù)器都有設(shè)置會(huì)話作廢間隔時(shí)間的選項(xiàng)。另外,也可以用編程的方式調(diào)用會(huì)話的setMaxInactiveInterval()方法,該方法用來設(shè)定在作廢會(huì)話之前,Servlet容器允許的客戶請(qǐng)求的最大間隔時(shí)間,以秒計(jì)。

22、使用緩沖標(biāo)記

一些應(yīng)用服務(wù)器加入了面向JSP的緩沖標(biāo)記功能。例如,BEA的WebLogic Server從6.0版本開始支持這個(gè)功能,Open

Symphony工程也同樣支持這個(gè)功能。JSP緩沖標(biāo)記既能夠緩沖頁面片斷,也能夠緩沖整個(gè)頁面。當(dāng)JSP頁面執(zhí)行時(shí),如果目標(biāo)片斷已經(jīng)在緩沖之中,則生成該片斷的代碼就不用再執(zhí)行。頁面級(jí)緩沖捕獲對(duì)指定URL的請(qǐng)求,并緩沖整個(gè)結(jié)果頁面。對(duì)于購物籃、目錄以及門戶網(wǎng)站的主頁來說,這個(gè)功能極其有用。對(duì)于這類應(yīng)用,頁面級(jí)緩沖能夠保存頁面執(zhí)行的結(jié)果,供后繼請(qǐng)求使用。

23、選擇合適的引用機(jī)制

在典型的JSP應(yīng)用系統(tǒng)中,頁頭、頁腳部分往往被抽取出來,然后根據(jù)需要引入頁頭、頁腳。當(dāng)前,在JSP頁面中引入外部資源的方法主要有兩種:include指令,以及include動(dòng)作。

include指令:例如%@ include file="copyright.html"

%。該指令在編譯時(shí)引入指定的資源。在編譯之前,帶有include指令的頁面和指定的資源被合并成一個(gè)文件。被引用的外部資源在編譯時(shí)就確定,比運(yùn)行時(shí)才確定資源更高效。

include動(dòng)作:例如jsp:include page="copyright.jsp"

/。該動(dòng)作引入指定頁面執(zhí)行后生成的結(jié)果。由于它在運(yùn)行時(shí)完成,因此對(duì)輸出結(jié)果的控制更加靈活。但時(shí),只有當(dāng)被引用的內(nèi)容頻繁地改變時(shí),或者在對(duì)主頁面的請(qǐng)求沒有出現(xiàn)之前,被引用的頁面無法確定時(shí),使用include動(dòng)作才合算。

24、及時(shí)清除不再需要的會(huì)話

為了清除不再活動(dòng)的會(huì)話,許多應(yīng)用服務(wù)器都有默認(rèn)的會(huì)話超時(shí)時(shí)間,一般為30分鐘。當(dāng)應(yīng)用服務(wù)器需要保存更多會(huì)話時(shí),如果內(nèi)存容量不足,操作系統(tǒng)會(huì)把部分內(nèi)存數(shù)據(jù)轉(zhuǎn)移到磁盤,應(yīng)用服務(wù)器也可能根據(jù)“最近最頻繁使用”(Most

Recently

Used)算法把部分不活躍的會(huì)話轉(zhuǎn)儲(chǔ)到磁盤,甚至可能拋出“內(nèi)存不足”異常。在大規(guī)模系統(tǒng)中,串行化會(huì)話的代價(jià)是很昂貴的。當(dāng)會(huì)話不再需要時(shí),應(yīng)當(dāng)及時(shí)調(diào)用HttpSession.invalidate()方法清除會(huì)話。HttpSession.invalidate()方法通??梢栽趹?yīng)用的退出頁面調(diào)用。

25、不要將數(shù)組聲明為:public static final 。

26、HashMap的遍歷效率討論

經(jīng)常遇到對(duì)HashMap中的key和value值對(duì)的遍歷操作,有如下兩種方法:MapString, String[] paraMap = new HashMapString, String[]();

................//第一個(gè)循環(huán)

SetString appFieldDefIds = paraMap.keySet();

for (String appFieldDefId : appFieldDefIds) {

String[] values = paraMap.get(appFieldDefId);

......

}

//第二個(gè)循環(huán)

for(EntryString, String[] entry : paraMap.entrySet()){

String appFieldDefId = entry.getKey();

String[] values = entry.getValue();

.......

}

第一種實(shí)現(xiàn)明顯的效率不如第二種實(shí)現(xiàn)。

分析如下 SetString appFieldDefIds = paraMap.keySet(); 是先從HashMap中取得keySet

代碼如下:

public SetK keySet() {

SetK ks = keySet;

return (ks != null ? ks : (keySet = new KeySet()));

}

private class KeySet extends AbstractSetK {

public IteratorK iterator() {

return newKeyIterator();

}

public int size() {

return size;

}

public boolean contains(Object o) {

return containsKey(o);

}

public boolean remove(Object o) {

return HashMap.this.removeEntryForKey(o) != null;

}

public void clear() {

HashMap.this.clear();

}

}

其實(shí)就是返回一個(gè)私有類KeySet, 它是從AbstractSet繼承而來,實(shí)現(xiàn)了Set接口。

再來看看for/in循環(huán)的語法

for(declaration : expression_r)

statement

在執(zhí)行階段被翻譯成如下各式

for(IteratorE #i = (expression_r).iterator(); #i.hashNext();){

declaration = #i.next();

statement

}

因此在第一個(gè)for語句for (String appFieldDefId : appFieldDefIds) 中調(diào)用了HashMap.keySet().iterator() 而這個(gè)方法調(diào)用了newKeyIterator()

IteratorK newKeyIterator() {

return new KeyIterator();

}

private class KeyIterator extends HashIteratorK {

public K next() {

return nextEntry().getKey();

}

}

所以在for中還是調(diào)用了

在第二個(gè)循環(huán)for(EntryString, String[] entry : paraMap.entrySet())中使用的Iterator是如下的一個(gè)內(nèi)部類

private class EntryIterator extends HashIteratorMap.EntryK,V {

public Map.EntryK,V next() {

return nextEntry();

}

}

此時(shí)第一個(gè)循環(huán)得到key,第二個(gè)循環(huán)得到HashMap的Entry

效率就是從循環(huán)里面體現(xiàn)出來的第二個(gè)循環(huán)此致可以直接取key和value值

而第一個(gè)循環(huán)還是得再利用HashMap的get(Object key)來取value值

現(xiàn)在看看HashMap的get(Object key)方法

public V get(Object key) {

Object k = maskNull(key);

int hash = hash(k);

int i = indexFor(hash, table.length); //Entry[] table

EntryK,V e = table;

while (true) {

if (e == null)

return null;

if (e.hash == hash eq(k, e.key))

return e.value;

e = e.next;

}

}

其實(shí)就是再次利用Hash值取出相應(yīng)的Entry做比較得到結(jié)果,所以使用第一中循環(huán)相當(dāng)于兩次進(jìn)入HashMap的Entry中

而第二個(gè)循環(huán)取得Entry的值之后直接取key和value,效率比第一個(gè)循環(huán)高。其實(shí)按照Map的概念來看也應(yīng)該是用第二個(gè)循環(huán)好一點(diǎn),它本來就是key和value的值對(duì),將key和value分開操作在這里不是個(gè)好選擇。


本文名稱:java減少代碼體積,java怎么優(yōu)化代碼減少內(nèi)存
本文URL:http://weahome.cn/article/hesiih.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部