1,AM: Creates an empty jar file entry (AM_CREATES_EMPTY_JAR_FILE_ENTRY)/AM: Creates an empty zip file entry (AM_CREATES_EMPTY_ZIP_FILE_ENTRY)
示例代碼:
ZipEntry entry = new ZipEntry(PATH);
zos.putNextEntry(entry);
zos.closeEntry();
原因:
代碼中在調用putNextEntry()之后緊接着調用了closeEntry()函數,致使該jar文件內容為空,因為打jar包的寫內容是在putNextEntry()和closeEntry()兩個函數調用之間來進行的。(有時候也許會有意的構建一個空目錄,因此不一定就是bug)
2,BC: Equals method should not assume anything about the type of its argument (BC_EQUALS_METHOD_SHOULD_WORK_FOR_ALL_OBJECTS)
示例代碼:
public class Foo {
// some code
public void equals(Object o) {
Foo other = (Foo) o;
// the real equals code
}
}
原因:
當你在實現類的equals方法時,不應該對參數有任何的預先設定。如上代碼所寫,則設定了參數o肯定是Foo類的一個對象.但是如果在函數調用時,參數o不是一個Foo類或其子類,就會導致代碼會拋出一個ClassCastException。因此在實現equals方法,應該加一個判斷,如果參數o不是一個Foo類對象,則返回false。
3,BC: Random object created and used only once (DMI_RANDOM_USED_ONLY_ONCE)
示例代碼:
public int getRandom(int seed) {
return new Random(seed).nextInt();
}
原因:
由於java.util.Random是一個偽隨機函數,如果傳入的seed值相同的話,返回的隨機數者是相同的 。因此沒必要每次都new一個新的random出來計算隨機數。如果你想真正地獲得一個不可預知的隨機數,建議使用java.security.SecureRandom,該類繼承自Random,是一個強隨機數生成器 。因此上述代碼可以修改為:
public class Test extends Thread{
private SecureRandom ran;
Test(int seed){
ran = new SecureRandom();
}
public int getRandom(int seed) {
return ran.nextInt();
}
}
4,CN: Class implements Cloneable but does not define or use clone method (CN_IDIOM)
示例代碼:
public class Foo implements Cloneable {
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
原因:
類定義要實現了 Cloneable接口,卻沒有定義或使用 clone方法,即缺少紅色字體部分。
5,CN: clone method does not call super.clone() (CN_IDIOM_NO_SUPER_CALL)
示例代碼:
public class Foo implements Cloneable {
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
原因:
clone方法沒有調用super.clone()方法,如果沒有調用,則會導致對象父子層級關系不能正確建立,最終導致無法正確組裝對象。
6,CN: Class defines clone() but doesn't implement Cloneable (CN_IMPLEMENTS_CLONE_BUT_NOT_CLONEABLE)
示例代碼:
public class Foo{
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
原因:
這個用法的意義在於你可以規范該類的子類的clone的實現,如果你的確想這樣做的話,這不是一個bug,否則的話是一個bug
7,DE: Method might drop exception (DE_MIGHT_DROP)/DE: Method might ignore exception (DE_MIGHT_IGNORE)
示例代碼:
try{}catch(Exception ex){}
原因:
方法有可能拋異常或者忽略異常,需要對異常進行處理,即需要在catch體中對異常進行處理。
8,DMI: Don't use removeAll to clear a collection (DMI_USING_REMOVEALL_TO_CLEAR_COLLECTION)
原因:
建議不要使用 collection.removeAll(collection)方法來刪除 collection中的所有元素,而使用collection.clear()。比較二者的代碼實現就可以看出:
removeAll()源碼:
public boolean removeAll(Collection<?> c) {
boolean modified = false;
Iterator<?> e = iterator();
while (e.hasNext()) {
if (c.contains(e.next())) {
e.remove();
modified = true;
}
}
return modified;
}
clear()源碼:
public void clear() {
Iterator<E> e = iterator();
while (e.hasNext()) {
e.next();
e.remove();
}
}
前者是比較參數中的collection和要移除元素的collection中是否有交集,然后將交集元素刪除;后者是直接將collenction中的元素刪除。顯然后者要比前者高效,而且對於某些特殊的collenction還容易拋出一些異常,如ConcurrentModificationException
9,ES: Comparison of String parameter using == or != (ES_COMPARING_PARAMETER_STRING_WITH_EQ)
原因:當比較兩個字符串內容是否相同時,僅當兩個字符串在源文件中都是常量時或者是使用intern()來比較才可以用==來比較,否則最好使用對象比較方法equal。附string比較:
String str1 = "java";
String str2 = "java";
System.out.print(str1==str2);
結果:true(二者都為常量)
String str1 = new String("java");
String str2 = new String("java");
System.out.print(str1==str2);
結果:false(二者為對象)
String str1 = "java";
String str2 = "blog";
String s = str1+str2;
System.out.print(s=="javablog");
結果:false(s不為常量,為對象)
String s1 = "java";
String s2 = new String("java");
System.out.print(s1.intern()==s2.intern());
結果:true(但是intern()方法在效率和實現方式上不統一)
