久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

推薦四十多條純干貨 Java 代碼優(yōu)化建議

 airen89 2018-12-23

代碼優(yōu)化最重要的作用應(yīng)該是避免未知的錯(cuò)誤,,因此在寫代碼的時(shí)候,從源頭開始注意各種細(xì)節(jié),,權(quán)衡并使用最優(yōu)的選擇,,將會(huì)很大程度上避免出現(xiàn)未知的錯(cuò)誤,從長遠(yuǎn)看也極大的降低了工作量,。所以說代碼優(yōu)化的目標(biāo)是減小代碼體積,、提高代碼運(yùn)行效率。優(yōu)化是無止境的,,本文也只給出整理的一些常見優(yōu)化建議,。

(1)盡量指定類、方法的 final 修飾符

帶有 final 修飾符的類是不可派生的,。在 Java 核心 API 中,,有許多應(yīng)用 final 的例子,例如 java.lang.String,,整個(gè)類都是 final 的,。為類指定 final 修飾符可以讓類不可以被繼承,為方法指定 final 修飾符可以讓方法不可以被重寫,。如果指定了一個(gè)類為 final,,則該類所有的方法都是 final 的。Java 編譯器會(huì)尋找機(jī)會(huì)內(nèi)聯(lián)所有的 final 方法,,內(nèi)聯(lián)對(duì)于提升 Java 運(yùn)行效率作用重大,,具體可以查閱 Java 運(yùn)行期優(yōu)化相關(guān)資料,此舉能夠使性能平均提高 50%,。

(2)盡量重用對(duì)象

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

(3)盡可能使用局部變量

調(diào)用方法時(shí)傳遞的參數(shù)以及在調(diào)用中創(chuàng)建的臨時(shí)變量都保存在棧中,,速度較快,,其他變量,如靜態(tài)變量、實(shí)例變量等,,都在堆中創(chuàng)建,,速度較慢。另外,,棧中創(chuàng)建的變量,,隨著方法的運(yùn)行結(jié)束,這些內(nèi)容就沒了,,不需要額外的垃圾回收,。

(4)及時(shí)關(guān)閉流。

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

//性能不好,list.size() 會(huì)重復(fù)調(diào)用
for (int i = 0; i <>
    ...
}

//建議替換為如下
for (int i = 0, length = list.size(); i <>
    ...
}
//如上寫法在 list.size() 很大的時(shí)候,,就減少了很多的消耗,。

(6)盡量采用懶加載的策略,即在需要的時(shí)候才創(chuàng)建,。

這個(gè)原則其實(shí)就是節(jié)約,,具體樣例如下。

//不好的示范
String str = 'aaa';
if (i == 1) {
  list.add(str);
}

//建議替換為如下
if (i == 1) {
  String str = 'aaa';
  list.add(str);
}

(7)慎用異常,。

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

(8)不要在循環(huán)中使用 try-catch,,應(yīng)該把其放在最外層

根據(jù)網(wǎng)友們提出的意見,,這一點(diǎn)我認(rèn)為值得商榷,其實(shí)分業(yè)務(wù)場景吧,有些場景需要循環(huán)終止,,有些只是為了忽略當(dāng)此循環(huán)處理,。

(9)如果能估計(jì)到待添加的內(nèi)容長度,為底層以數(shù)組方式實(shí)現(xiàn)的集合,、工具類指定初始長度

比如 ArrayList,、LinkedLlist、StringBuilder,、StringBuffer,、HashMap、HashSet 等,,以 StringBuilder 為例,,StringBuilder() 構(gòu)造方法默認(rèn)分配 16 個(gè)字符的空間,StringBuilder(int size) 構(gòu)造方法默認(rèn)分配 size 個(gè)字符的空間,,StringBuilder(String str) 構(gòu)造方法默認(rèn)分配 16 個(gè)字符加 str.length() 個(gè)字符空間,,所以可以通過類的構(gòu)造方法來設(shè)定它的初始化容量,這樣可以明顯地提升性能,。

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

這個(gè)肯定大家都沒有疑問的,,性能優(yōu)化的實(shí)現(xiàn)而已,。

(11)乘法和除法使用移位操作。

用移位操作可以極大地提高性能,,因?yàn)樵谟?jì)算機(jī)底層,,對(duì)位的操作是最方便、最快的,,但是移位操作雖然快,,可能會(huì)使代碼不太好理解,因此最好加上相應(yīng)的注釋,。

//不好的示范
for (val = 0; val <>100000; val += 5) {
  a = val * 8;
  b = val / 2;
}

//建議修改實(shí)現(xiàn)
for (val = 0; val <>100000; val += 5) {
  a = val <>3;
  b = val >> 1;
}

(12)循環(huán)內(nèi)不要不斷創(chuàng)建對(duì)象引用,。

見如下案例解釋分析原因。

//不好的示范
for (int i = 1; i <>
    Object obj = new Object();    
}

//上面這種做法會(huì)導(dǎo)致內(nèi)存中有 count 份 Object 對(duì)象引用存在,,
//count 很大的話,,就耗費(fèi)內(nèi)存了,建議為如下實(shí)現(xiàn),。
Object obj = null;
for (int i = 0; i <>
    obj = new Object();
}
//如上實(shí)現(xiàn)內(nèi)存中只有一份 Object 對(duì)象引用,,
//每次 new Object() 的時(shí)候,Object 對(duì)象引用指向不同的 Object 罷了,,
//但是內(nèi)存中只有一份,,這樣就大大節(jié)省了內(nèi)存空間了,。

(13)基于效率和類型檢查的考慮,應(yīng)該盡可能使用 array,,無法確定數(shù)組大小時(shí)才使用 ArrayList,。

(14)盡量使用 HashMap、ArrayList,、StringBuilder,,除非線程安全需要,否則不推薦使用 Hashtable,、Vector,、StringBuffer,后三者由于使用同步機(jī)制而導(dǎo)致了性能開銷,。

(15)不要將數(shù)組聲明為 public static final,。

因?yàn)檫@毫無意義,這樣只是定義了引用為 static final,,數(shù)組的內(nèi)容還是可以隨意改變的,,將數(shù)組聲明為 public 更是一個(gè)安全漏洞,這意味著這個(gè)數(shù)組可以被外部類所改變,。

(16)盡量在合適的場合使用單例,。

使用單例可以減輕加載的負(fù)擔(dān)、縮短加載的時(shí)間,、提高加載的效率,,但并不是所有地方都適用于單例,簡單來說,,單例主要適用于以下三個(gè)方面:

控制資源的使用,,通過線程同步來控制資源的并發(fā)訪問;

控制實(shí)例的產(chǎn)生,,以達(dá)到節(jié)約資源的目的,;

控制數(shù)據(jù)的共享,在不建立直接關(guān)聯(lián)的條件下,,讓多個(gè)不相關(guān)的進(jìn)程或線程之間實(shí)現(xiàn)通信,;

(17)盡量避免隨意使用靜態(tài)變量。

因?yàn)楫?dāng)某個(gè)對(duì)象被定義為 static 的變量所引用,,那么 gc 通常是不會(huì)回收這個(gè)對(duì)象所占有的堆內(nèi)存的,。

public class A {
    private static B b = new B();  
}
//此時(shí)靜態(tài)變量 b 的生命周期與 A 類相同,
//如果 A 類不被卸載,,那么引用 B 指向的 B 對(duì)象會(huì)常駐內(nèi)存,,直到程序終止。

(18)及時(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ì)把部分?jǐn)?shù)據(jù)轉(zhuǎn)移到磁盤,,應(yīng)用服務(wù)器也可能根據(jù)MRU(最近最頻繁使用)算法把部分不活躍的會(huì)話轉(zhuǎn)儲(chǔ)到磁盤,,甚至可能拋出內(nèi)存不足的異常。如果會(huì)話要被轉(zhuǎn)儲(chǔ)到磁盤,,那么必須要先被序列化,,在大規(guī)模集群中,對(duì)對(duì)象進(jìn)行序列化的代價(jià)是很昂貴的,。因此,,當(dāng)會(huì)話不再需要時(shí),應(yīng)當(dāng)及時(shí)調(diào)用 HttpSession 的 invalidate() 方法清除會(huì)話,。

(19)實(shí)現(xiàn) RandomAccess 接口的集合(比如 ArrayList)應(yīng)當(dāng)使用最普通的 for 循環(huán)而不是 foreach 循環(huán)來遍歷,。

這是 JDK 推薦給用戶的,JDK API 對(duì)于 RandomAccess 接口的解釋是實(shí)現(xiàn) RandomAccess 接口用來表明其支持快速隨機(jī)訪問,,此接口的主要目的是允許一般的算法更改其行為,,從而將其應(yīng)用到隨機(jī)或連續(xù)訪問列表時(shí)能提供良好的性能。實(shí)際經(jīng)驗(yàn)表明,,實(shí)現(xiàn) RandomAccess 接口的類實(shí)例,,假如是隨機(jī)訪問的,使用普通 for 循環(huán)效率將高于使用 foreach 循環(huán),,反過來,,如果是順序訪問的,則使用 Iterator 會(huì)效率更高,。

//樣板代碼:可以使用類似如下的代碼作判斷,。
if (list instanceof RandomAccess) {
    for (int i = 0; i <>
else {
    Iterator iterator = list.iterable();
    while (iterator.hasNext()){iterator.next()}
}

(20)使用同步代碼塊替代同步方法。

盡量使用同步代碼塊,,避免對(duì)那些不需要進(jìn)行同步的代碼也進(jìn)行了同步,,影響了代碼執(zhí)行效率。

(21)將常量聲明為 static final,,并以大寫命名,。

這樣在編譯期間就可以把這些內(nèi)容放入常量池中,避免運(yùn)行期間計(jì)算生成常量的值,。另外,,將常量的名字以大寫命名也可以方便區(qū)分出常量與變量。

(22)不要?jiǎng)?chuàng)建一些不使用的對(duì)象,,不要導(dǎo)入一些不使用的類,。

這毫無意義,,如果代碼中出現(xiàn) 'The value of the local variable i is not used'、'The import java.util is never used',,那么請刪除這些無用的內(nèi)容,,雖說沒啥影響,但是有些時(shí)候編譯期會(huì)報(bào)錯(cuò),,譬如沒 import 用到的類被刪掉了,。

(23)程序運(yùn)行過程中避免使用反射。

不建議在程序運(yùn)行過程中使用,,除非萬不得已,,尤其是頻繁使用反射機(jī)制,特別是 Method 的 invoke 方法,,如果確實(shí)有必要,,一種建議性的做法是將那些需要通過反射加載的類在項(xiàng)目啟動(dòng)的時(shí)候通過反射實(shí)例化出一個(gè)對(duì)象并放入內(nèi)存,用戶只關(guān)心和對(duì)端交互的時(shí)候獲取最快的響應(yīng)速度,,并不關(guān)心對(duì)端的項(xiàng)目啟動(dòng)花多久時(shí)間,。

(24)使用數(shù)據(jù)庫連接池和線程池。

這兩個(gè)池都是用于重用對(duì)象的,,前者可以避免頻繁地打開和關(guān)閉連接,,后者可以避免頻繁地創(chuàng)建和銷毀線程。

(25)使用帶緩沖的輸入輸出流進(jìn)行 IO 操作,。

帶緩沖的輸入輸出流,,即 BufferedReader、BufferedWriter,、BufferedInputStream,、BufferedOutputStream,這可以極大地提升 IO 效率,。

(26)順序插入和隨機(jī)訪問比較多的場景使用 ArrayList,,元素刪除和中間插入比較多的場景使用 LinkedList。

(27)不要讓 public 方法中有太多的形參,。

public 方法即對(duì)外提供的方法,,如果給這些方法太多形參的話主要壞處是違反了面向?qū)ο蟮木幊趟枷耄琂ava 講求一切都是對(duì)象,,太多的形參和面向?qū)ο蟮木幊趟枷氩⒉黄鹾?,參?shù)太多勢必導(dǎo)致方法調(diào)用的出錯(cuò)概率增加。

(28)字符串變量和字符串常量 equals 的時(shí)候?qū)⒆址A繉懺谇懊?,這樣可以避免空指針,。

(29)建議使用 if (i == 1) 而不是 if (1 == i) 的方式。

因?yàn)橛锌赡?== 會(huì)誤寫成 =,,而在 C/C++ 中 if (i = 1) 是會(huì)出問題的,,而 Java 會(huì)在編譯時(shí)報(bào)錯(cuò) 'Type mismatch: cannot convert from int to boolean',,但是,盡管Java的 if (i == 1) 和 if (1 == i) 在語義上沒有任何區(qū)別,,從閱讀習(xí)慣上講,,建議使用前者會(huì)更好些。

(30)不要對(duì)數(shù)組使用 toString() 方法,。

本意是想打印出數(shù)組內(nèi)容,,卻打出來的是對(duì)象信息,,甚至有可能因?yàn)閿?shù)組引用為空而導(dǎo)致空指針異常,。對(duì)于集合 toString() 是可以打印出集合里面的內(nèi)容的,因?yàn)榧系母割?AbstractCollections 重寫了 Object 的 toString() 方法,。

(31)不要對(duì)超出范圍的基本數(shù)據(jù)類型做向下強(qiáng)制轉(zhuǎn)型,。
這很明確,譬如 long 轉(zhuǎn) int 是會(huì)存在潛在風(fēng)險(xiǎn)的,。

(32)公用的集合類中不使用的數(shù)據(jù)一定要及時(shí) remove 掉,。

如果一個(gè)集合類是公用的(也就是說不是方法里面的屬性),那么這個(gè)集合里面的元素是不會(huì)自動(dòng)釋放的,,因?yàn)槭冀K有引用指向它們,。所以,如果公用集合里面的某些數(shù)據(jù)不使用而不去remove掉它們,,那么將會(huì)造成這個(gè)公用集合不斷增大,,使得系統(tǒng)有內(nèi)存泄露的隱患。

(33)把一個(gè)基本數(shù)據(jù)類型轉(zhuǎn)為字符串,,基本數(shù)據(jù)類型.toString() 是最快的方式,、String.valueOf(數(shù)據(jù)) 次之、數(shù)據(jù)+'' 最慢,。

因?yàn)?String.valueOf() 方法底層調(diào)用了 Integer.toString() 方法,,但是會(huì)在調(diào)用前做空判斷;Integer.toString() 是直接調(diào)用,;i + '' 底層使用了 StringBuilder 實(shí)現(xiàn),,先用 append 方法拼接,再用 toString() 方法獲取字符串,。

(34)使用最有效率的方式去遍歷 Map,。

遍歷 Map 的方式有很多,通常場景下我們需要的是遍歷 Map 中的 Key 和 Value,,那么推薦使用的,、效率最高的方式是 entrySet(),如果只是想遍歷一下這個(gè) Map 的 key 值則 keySet() 會(huì)比較合適一些,。

(35)對(duì)資源的 close() 建議分開操作,。

雖然有些麻煩,,卻能避免資源泄露,這其實(shí)和 try-catch 機(jī)制相關(guān),,各自分開 close 各自的 try-catch 就會(huì)互不影響,,防止寫在一個(gè) try-catch 中因?yàn)橐粋€(gè)異常了后面的釋放不了。

(36)對(duì)于 ThreadLocal 在線程池場景使用前或者使用后一定要先 remove,。

因?yàn)榫€程池技術(shù)做的是一個(gè)線程重用,,這意味著代碼運(yùn)行過程中一條線程使用完畢并不會(huì)被銷毀而是等待下一次的使用,而 Thread 類中持有 ThreadLocal.ThreadLocalMap 的引用,,線程不銷毀意味著上條線程 set 的 ThreadLocal.ThreadLocalMap 中的數(shù)據(jù)依然存在,,那么在下一條線程重用這個(gè) Thread 的時(shí)候很可能 get 到的是上條線程 set 的數(shù)據(jù)而不是自己想要的內(nèi)容。這個(gè)問題非常隱晦,,一旦出現(xiàn)這個(gè)原因?qū)е碌腻e(cuò)誤,,沒有相關(guān)經(jīng)驗(yàn)或者沒有扎實(shí)的基礎(chǔ)非常難發(fā)現(xiàn)這個(gè)問題,因此在寫代碼的時(shí)候就要注意這一點(diǎn),,這將給你后續(xù)減少很多的工作量,。

(37)切記以常量定義的方式替代魔鬼數(shù)字,魔鬼數(shù)字的存在將極大地降低代碼可讀性,,字符串常量是否使用常量定義可以視情況而定,。

(38)long 或者 Long 初始賦值時(shí)使用大寫的 L 而不是小寫的 l,因?yàn)樽帜?l 極易與數(shù)字 1 混淆,,這個(gè)點(diǎn)非常細(xì)節(jié),,值得注意。

(39)所有重寫的方法必須保留 @Override 注解,。

這么做可以清楚地知道這個(gè)方法由父類繼承而來,,同時(shí)可以保證重寫成功,此外在抽象類中對(duì)方法簽名進(jìn)行修改,,實(shí)現(xiàn)類會(huì)馬上報(bào)出編譯錯(cuò)誤,。

(40)推薦使用 JDK7 中新引入的 Objects 工具類來進(jìn)行對(duì)象的 equals 比較,直接 a.equals(b) 有空指針異常的風(fēng)險(xiǎn),。

(41)循環(huán)體內(nèi)不要使用 '+' 進(jìn)行字符串拼接,,而直接使用 StringBuilder 不斷 append。

因?yàn)槊看翁摂M機(jī)碰到 '+' 這個(gè)操作符對(duì)字符串進(jìn)行拼接的時(shí)候會(huì) new 出一個(gè) StringBuilder,,然后調(diào)用 append 方法,,最后調(diào)用 toString() 方法轉(zhuǎn)換字符串賦值給對(duì)象,所以循環(huán)多少次,,就會(huì) new 出多少個(gè) StringBuilder() 來,,這對(duì)于內(nèi)存是一種浪費(fèi)。

(42)不捕獲 Java 類庫中定義的繼承自 RuntimeException 的運(yùn)行時(shí)異常類。

異常處理效率低,,RuntimeException 的運(yùn)行時(shí)異常中絕大多數(shù)完全可以由程序員來規(guī)避,,比如 ArithmeticException 可以通過判斷除數(shù)是否為空來規(guī)避,NullPointerException 可以通過判斷對(duì)象是否為空來規(guī)避,,IndexOutOfBoundsException 可以通過判斷數(shù)組/字符串長度來規(guī)避,,ClassCastException 可以通過 instanceof 關(guān)鍵字來規(guī)避,ConcurrentModificationException 可以使用迭代器來規(guī)避,。

(43)靜態(tài)類,、單例類、工廠類將它們的構(gòu)造函數(shù)置為 private,。

這是因?yàn)殪o態(tài)類,、單例類、工廠類這種類本來我們就不需要外部將它們 new 出來,,將構(gòu)造函數(shù)置為 private 之后,,保證了這些類不會(huì)產(chǎn)生實(shí)例對(duì)象,。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請遵守用戶 評(píng)論公約

    類似文章 更多