首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java 代碼審查檢查清單:11 種常見錯誤與最佳實踐(從字串拷貝到陣列複製)

     編輯:Java 程式設計入門

前言

代碼審查是消滅 Bug 最有效手段之一,能發現測試難覆蓋的細節錯誤。本文整理 11 類 Java 常見審查盲點,建議加入團隊 Checklist。

錯誤 1:多次拷貝不可變物件(String 為例)

// ❌ 多餘
String s = new String("Text here");
String s2 = new String(temp);

// ✅ 直接引用常量池
String s = "Text here";

原則:String、包裝類型、BigInteger 等不可變物件無需拷貝,直接傳回參考即可。

錯誤 2:Getter 回傳可變內部物件引用(破壞封裝)

// ❌ 危險
private Dimension d = new Dimension(0,0);
public Dimension getValues() { return d; } // 呼叫端可任意修改 d.width/height

// ✅ 回傳防禦性拷貝
public Dimension getValues() { return new Dimension(d.width, d.height); }

// ✅ 或回傳不可變視圖(Java 8+)
public List getTags() { return Collections.unmodifiableList(tags); }

錯誤 3:對不可變物件做不必要的防禦性拷貝

// ❌ 多餘
private Integer i = 0;
public Integer getValue() { return new Integer(i.intValue()); }

// ✅ 直接回傳
public Integer getValue() { return i; }

判斷依據:類別是否為 final 且無可變方法(String、所有基本型別包裝類、BigDecimal 等)。

錯誤 4:手寫迴圈複製陣列

// ❌ 低效、易出錯
int[] copy = new int[src.length];
for (int i = 0; i < src.length; i++) copy[i] = src[i];

// ✅ 標準庫
int[] copy = src.clone();           // 基本型別/物件參考淺拷貝
int[] copy = Arrays.copyOf(src, src.length);
int[] copy = Arrays.copyOfRange(src, 0, src.length);
System.arraycopy(src, 0, copy, 0, src.length); // 效能最佳

錯誤 5:equals() 未處理 null、未檢查型別、未覆寫 hashCode()

// ✅ 標準範本
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    MyClass that = (MyClass) o;
    return Objects.equals(field1, that.field1) &&
           Objects.equals(field2, that.field2);
}
@Override
public int hashCode() { return Objects.hash(field1, field2); }

錯誤 6:compareTo() 與 equals() 不一致

實作 Comparable 時,a.compareTo(b) == 0 應蘊含 a.equals(b) == true,否則 TreeSet/TreeMap 行為異常。

錯誤 7:在 finally 區塊回傳值/拋異常

// ❌ 吞噬原始異常
try { risky(); } finally { return defaultVal; }

// ✅ 正確
try { return risky(); } finally { cleanup(); }

錯誤 8:HashMap 鍵為可變物件且修改後未重新放入

修改鍵物件的 hashCode() 相關欄位會導致找不到原 Entry。鍵必須不可變,或修改後 remove -> put。

錯誤 9:SimpleDateFormat 宣告為靜態共用(非執行緒安全)

// ❌ 併發環境下會產生亂碼/拋異常
private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd");

// ✅ ThreadLocal 或 Java 8 DateTimeFormatter
private static final ThreadLocal TL = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
// 或
private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd"); // 不可變、執行緒安全

錯誤 10:捕獲異常後未保留堆疊(throw new MyException(e.getMessage()))


// ❌ 丟失原始堆疊
catch (SQLException e) { throw new DaoException(e.getMessage()); }

// ✅ 保留因果鏈
catch (SQLException e) { throw new DaoException("查詢失敗", e); }

錯誤 11:資源未關閉(Connection/Stream/檔案)


// ✅ Java 7+ try-with-resources
try (Connection c = ds.getConnection();
     PreparedStatement ps = c.prepareStatement(sql);
     ResultSet rs = ps.executeQuery()) {
    // 使用資源
} // 自動關閉,即使拋異常

總結:審查時的「三問法」

  1. 這個物件是否不可變?若是,別拷貝。
  2. 這個方法是否洩露內部可變狀態?若是,回傳拷貝或不可變視圖。
  3. 資源(連線、流、鎖)是否在所有路徑(正常/異常)都確實釋放?

將這 11 項納入團隊 Code Review Checklist,配合 SonarQube/SpotBugs 靜態分析,可大幅降低生產事故率。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved