做過幾年的Java開發,也閱讀過一些新手寫的Java代碼,常常會發現一些Java開發人員經常犯的一些錯誤,是以将Java開發中常見錯誤整理如下:
1.NullPointException問題
這種錯誤恐怕是程式設計初期最容易犯的錯誤。 Java是面向對象的語言, 操作幾乎都是在對象之間進行的, 一個類的執行個體如果是空(null)的話則不能調用這個執行個體的方法, 否則就會出java.lang.NullPointException錯誤。 最常見的String的操作, 如:
String str = null;
if (str.equals(“Hello”)) {
System.out.println(“str is Hello”);
}
常用的避免方法就是在使用一個Object之前要判斷一下是否為null, 除非你确定它肯定是不為null的。是以應該上例修改如下:
String str = null;
if (str !=null && str.equals(“Hello”)) {
System.out.println(“str is Hello”);
}
對于String的這種equals或equalsIgnoreCase的操作常常還可以用下面的方法進行安全操作:
String str = null;
if (“Hello”.equals(str)) {
System.out.println(“str is Hello”);
}
用一個确定的不為null的String去與未知的String進行比較。
2.多餘處理語句
這種問題當然不隻是java才有的, 任何程式都有可能出現多餘的垃圾代碼, 盡管它的最終結果是正确的, 我們在寫程式的時候要盡可能避免這種不必要的處理。
常見的情況有以下幾種:
2.1多餘的執行個體構造
聲明了一個對象的執行個體, 有的人喜歡同時new一下,即給它配置設定了空間, 而在後面并沒用到配置設定的空間, 而是進行了其它的操作,例:
ArrayList resultList = new ArrayList();
try {
resultList = SomeModule.getResultList();
} catch (Exception e) {
return null;
}
…
resultList在聲明的時候同時給它配置設定了空間, 但在下面卻用它指向了另外傳回的位址。 雖然在寫Java程式的時候我們不用考慮記憶體的配置設定等令人頭疼的問題, Java有自己的一套記憶體管理機制, 但Java在對象的構造的時候開銷是很大的, 是以諸如此類的浪費效率的處理還是得要注意避免。
2.2循環多餘
我們經常會從一個數組或Collection中通過循環來找出一個符合條件的元素進行操作, 而在執行完之後往往會忘記跳出循環體。 例:
String[] week = new String[]{“Sun”, “Mon”, “Tue”, “Wen”, “Thu”, “Fri”, “Sat”};
for (int i = 0; i < week.length; i++) {
if (week.equals(“Tue”)) {
System.out.println(“Tue is found”);
}
}
如果上面這段程式隻是找出week中是否有Tue的話,則在找到之後應該跳出循環體, 正确的寫法如下:
for (int i = 0; i < week.length; i++) {
if (week.equals(“Tue”)) {
System.out.println(“Tue is found”);
break; (或return)
}
}
…
循環處理的原則就是在處理完畢的地方跳出。
2.3 重複語句
建議如果有兩個或兩個以上的地方需要用到相同的程式塊代碼, 就要考慮到使用函數, 如果一個功能塊比較獨立, 有可能在其它被調用, 這個時候也盡可能的使用方法獨立開來。
還有種情況就是在條件分支語句裡面, 各個分支都需要執行某個相同的語句, 這個時候就需要提到分支的外面去執行。
3.數組和集合的使用問題
3.1數組下标越界的問題;
現在程式中大多都有對數組的操作,是以在調用數組的時候一定要認真檢查,看自己調用的下标是不是超出了數組的範圍,一般來說,顯示(即直接用常數當下标) 調用不太容易出這樣的錯,但隐式(即用變量表示下标)調用就經常出錯了,還有一種情況,是程式中定義的數組的長度是通過某些特定方法決定的,不是事先聲明 的,這個時候,最好先檢視一下數組的length,以免出現這個異常。
3.2 不能合理的使用集合的問題;
不清除List、Set和Map等集合的差別,該使用Set集合的時候使用List;不知道集合的合适的使用場合的問題。
4.資源不釋放的問題
IO操作要注意,打開記得要關閉。資料庫資源和網絡接等資源也是同樣的道理。打開的資源連接配接記得要關閉。
5.語句備援的問題
“簡練是良好的寫作風格”,寫文章如此,寫代碼也是如此。因為簡練的代碼一般有三個好處:1.節省你的編寫時間;2.節省維護者的閱讀時間;3.提高代碼的運作效率。
例如:params.put("status", new Integer(Status.DELETED.getValue()));
改進:該語句應該充分使用Java的自動包裝功能。不要去new Integer 對象,因為這樣既有代碼備援,又會重複的構造對象,降低程式的運作效率。
例如:if (isAdmin == true) {
this.appserviceService.deleteAdminApp(id);
}
可以簡化為if (isAdmin) {
this.appserviceService.deleteAdminApp(id);
}
6.使用被廢棄的方法的問題
一般API中廢棄的方法一定是存在着某種問題是以應該盡量避免使用。
例如:if (date.getYear() > value.getYear()) { ... }
此處Date對象的getYear()的方法被廢棄了。應該使用Calendar.get(Calendar.YEAR)去代替;
7.代碼淩亂的問題
代碼是思路的表達,程式設計首先應該整理思路,編碼也像寫文章一樣,應該條理清晰,段落分明。按照解決問題的步驟去分段寫代碼,每段代碼的功能應該很明确。該寫成獨立方法的要使用獨立的方法去實作。
8.不能充分使用Java5的新特性的問題
應該充分的使用Java5的Autoboxing/Unboxing功能,Generics(泛型),Varargs(可變參數)等功能來編寫代碼,進而使用代碼更加簡潔和健壯。
9.對常用的API不熟悉的問題
“Don't Reinvent the Wheel”--不要重複發明輪子,要熟悉jdk和apache常用包的API,沒有充足的理由就不要去寫别人已經寫過的方法。“君子善假于物也”,熟悉常用的API,熟練的去使用它們吧!
10.不必要的類型轉化的問題
也許是對字元串類型過于熱愛的緣故吧,經常發現有些代碼原本可以使用Integer或者Date類型去做的事情,有些工程師卻熱衷于将其轉化為字元串類型,需要知道類型轉化是需要付出額外的時間成本的。這樣的代碼既啰嗦又影響代碼的效率。
11.代碼注釋的問題
注釋代碼時,要考慮到不僅将來維護你代碼的開發人員要看,而且你自己也可能要看。用Phil Haack大師的話來說就是:“一旦一行代碼顯示螢幕上,你也就成了這段代碼的維護者”。是以,對于我們寫得好(差)的注釋而言,我們将是第一個受益者(受害者)。
注釋的黃金規則:易讀的代碼,人性化的去書寫代碼。這個很重要。寫代碼要對自己負責,對維護者負責。
對每個方法都要說明:功能、每個參數的意義,參數可以取哪些值,傳回值有哪些,在什麼情況下傳回什麼值。對每個源檔案都要在開頭以注釋的方式說明它的作用。
還有的注釋是無用,這樣的注釋也不應該出現,不要侮辱閱讀代碼者的智商如:
if (a == 5) // if a equals 5
counter = 0; // set the counter to zero
這樣顯而易見的注釋就不需要寫了,寫這些無用的注釋隻會會浪費你的時間,并将轉移讀者對該代碼細節的了解。
12.代碼格式的問題
盡量遵照規範去格式化代碼,該換行的換行,該空格的空格,該縮進需要縮進,以提高代碼的可讀性。
13.命名規範的問題
命名規範使程式更易讀,進而更易于了解。它們也可以提供一些有關辨別符功能的資訊,以助于了解代碼,例如,不論它是一個常量,包,還是類。Java語言中包、類、方法、變量和常量都有其命名規範。在Java語言命名規範網上有很多很好的文章,這裡就不再贅述。
以上是本人整理的Java開發中的常見問題(其中有些問題也适用其它開發語言),歡迎大家參與讨論,提出自己的看法,或者發表自己的見解。