笑着 胖胖蘭原創,轉載請註明。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
http://blog.csdn.net/bluesmile979/archive/2008/10/19/3105274.aspx
在這一篇文章中,笑着想要聊一聊跟Java語言相關的,需要注意的一些規範。
1. 關於基礎數據類型。
還記得上一片文章中結尾部分的那個例子麼?
因爲計算機的2進制的特性,Java語言(其他語言好像也一樣)無法準確地進行float,double類型數據的計算,所以,作這些計算的時候需要考慮使用BigDecimal着各類。
2. String類與StringBuffer類
Java的String類提供如下的簡單的字符串連接方法。
String s1 = “a”;
String s2 = “b”;
String s3 = “c”;
String s = s1 + s2 + s3;
但是這裏有一個問題,String類的每一次加操作都會產生一個新的對象。當你針對String類的加的操作開始變得多起來的時候,不但程序佔用內存會增加得非常明顯,程序運行時間也會大大增加。這個時候需要考慮StringBuffer類的append方法。笑着不是一個極端主義者,所以,笑着還是傾向,不要只要對字符串採用加的操作就用append方法。而是應該根據具體情況,自己衡量一下。具體的測試,自己寫個for循環1w次,很容易測試出來的。
3. 關於import*
儘量不要採用import*的寫法,而是應該把要import的類具體寫出來。這裏的原因,一個是因爲import*的寫法會影響程序的閱讀,導致維護者不是很清楚你具體用到了哪些類。但是更主要的是,如果你import*,那麼在你打包生成jar,war等等文件的時候,你的*代表的所有類都會被打包進去。一方面導致了你發佈內容的大小大幅度增加,另外,很可能會泄漏了一些你並不想要泄露出去的內容。這纔是問題的關鍵,安全第一。
4. 合理使用異常處理,不要過度使用。
Java得異常處理是個不錯的東西。可以節省我們很多工作量。但是,有異常處理的的代碼段比沒有異常處理的代碼段運行的時間要增加不少。所以不要把什麼都交給異常處理。我們應該做出適當的判斷,最後的最後,處理不了的東西才應該交給異常處理,這也符合業務處理的邏輯。
比如,存在FileNotFoundException,但是,
try {
} catch ( FileNotFoundException ) {
}
就不如
if ( f.exists() ) {
} else {
}
5. 儘量不要簡單的捕捉Exception異常。
因爲在Java裏面舊的異常會被新的異常所淹沒,而使得我們僅僅根據新的異常信息很難判斷出問題究竟出在什麼地方。而簡單的捕捉Exception異常,會使得這種可能性大大增加。另外,簡單的捕捉Exception異常會使得我們很難針對不同的異常採取對應的措施。所以請儘量捕捉具體的異常而不是Exception這個超級異常。可以考慮如下代碼結構。
try {
} catch() {
} catch() {
} catch(Exception) {
}
關於Java裏面舊的異常會被新的異常所淹沒地解決辦法,一般是需要自己來實現一些異常類的,因爲不是這一篇文章的重點,這裏不打算具體討論。
6. 不要重複生成你的對象。Java中new一個新的對象,相對的是要花費比較多的時間的。雖然現在的CPU可能不太在乎這麼點時間。但是積少成多啊。可能new一次的,就儘量不要new兩次了。目前階段能夠接觸到的是要在循環體外而不是循環體內new除你的對象,這很簡單,也很容易注意到。但是在複雜的系統中,如何儘量減少你new一個對象的次數,是否需要使用static關鍵字,就並不是那麼明顯,那麼容易被考慮到,解決掉了。而且考慮到可維護性,代碼結構,等等因素,取捨角度也是不同的。至少,我們先記住這樣的原則。不要重複生成你的對象。
7. 不要在你的循環體內做一些不必要的計算。比如:
for(;;al.size()){}
不如:
int size = al.size();
for(;;size){}
雖然看過文章好像說Java編譯器會做優化,這兩種寫法是一樣的。但是基本原則“不要在你的循環體內做一些不必要的計算。”我想這是不會有任何不同意見的。笑着不喜歡記那麼多東西,記不住。對於編譯器到底做哪些優化笑着也覺得是個沒有什麼承諾的事情。還是自己控制更安心一點。當然,當後一種寫法嚴重影響了你的代碼可讀性的時候,可以在效率和可讀性之間作一個權衡。畢竟現在的CPU還是很強悍的,循環次數不是很多的話效率的影響基本可以忽略。
8. String 的==與equal()
在對字符串的相等判斷,==判斷的是地址是否相同,equal()判斷的是字符值是否相同。大多數時候==跟equal()的結果都是相同的。這是因爲String對象是不變模式的,如果你不是明確地new一個String對象,Java對於String對象的保存默認的是會把新生成的String對象放到一個緩衝區,然後每次判斷緩衝區中是否已經有了這個對象,如果有了,那麼後建立的同樣字符值的String對象也會指向最初建立是該字符值對象的地址。也就是說字符值相同的時候,大多數情況下地質也是相同的。==與equal()效果是相同的。但是當對象是str = new String(“abc”)生成的而不是直接str = “abc”這樣賦值生成,或者經過了一些字符串連接處理,或者通過StringBuffer等對象生成,都會在內存中開闢新的地址的,這個時候==和equal()結果是不同的。
是不是稍微有些複雜?這裏需要一些關於內存,堆棧,對象保存方面的理解。笑着不想糾纏於這個問題的討論。如果不能理解,那麼只要記住如果你想要判斷兩個字符串的字符值是否相等,沒有別的要求的時候,那麼請使用equal()而不是==,至於什麼時候需要使用==,我想當你需要的時候,你自然就會明白了。實際上,對於字符串的判斷,我們很少需要用的==的。
9. 關於str.equal(“abc”)和”abc”.equal(str)
這個好像爭論也挺多的,第一種常量寫在後面可能符合大多數人的習慣,也符合我們的邏輯思維。但是需要多一個str是否爲null的判斷。否則這裏是有可能出現異常的。而後一種寫法不需要多做關於是否爲null這個判斷。就笑着個人喜好來說,比較喜歡後一種寫法。
10. Java是傳值還是傳引用?
曾經,Java程序員都是從C++轉過來的,大家最愛討論的就是這個冒似高深實際卻很無聊的問題。笑着不懂什麼叫做傳值什麼叫做傳引用。笑着只想提醒大家記住下面的事實,記住就足夠了。到底這種事實說明了Java是傳值還是傳引用,爭論下去有什麼意義麼?
事實是,在一個方法裏面,對他的參數對象本身是無法改變的。比如:
private void changeParam1(XXXClass _pc){
_pc = new XXXClass();// 想要改變參數對象本身。
}
上面代碼的_pc = new XXXClass();操作,只是在函數體內部生效。除了函數體,你傳給這個函數的對象是什麼,那他還是什麼。就是說你在函數內部是無法改變參數所指向的內存地址的。你是無法改變參數對象本身本身的。這裏,爭論的產生就是C++程序員非常喜歡的一個好象叫做Swap的函數,在Java裏面無法同樣實現了。
但是,Java裏面是可以對參數對象的屬性進行變更的。
private void changeParam2(XXXClass _pc){
_pc.setField(fieldValue)// 想要改變參數對象的屬性。
}
如上代碼是可以實現你的意圖的。
至於原因,需要畫畫內存中對象存儲,對象指向才能說清楚。笑着覺得那沒有研究的價值。記住結論就好了。畫圖好累的,笑着就偷懶不畫了。
11.
適當考慮Java的跨平臺性,儘量使用Java提供給你的功能。
比如,換行回車到底是/r/n還是/r或者是/n,不同的系統是不一樣的。所以考慮一下使用Java提供的功能吧
System類中提供public static String getProperty(String key)方法,其中key可以取如下的值。
file.separator |
文件分隔符(在 UNIX 系統中是“/”) |
path.separator |
路徑分隔符(在 UNIX 系統中是“:”) |
line.separator |
行分隔符(在 UNIX 系統中是“/n”) |
12.