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

《編寫高質量代碼:改善 Java 程序的 151 個建議》精讀筆記(建議 6-10)

     編輯:Java 綜合教學

建議 6:覆寫變長參數方法也要循規蹈矩

核心規則:覆寫方法的**參數列表必須與父類完全一致**,包括類型、數量、**顯示形式**(變長參數 int... args vs 數組 int[] args)。

反面案例

class Base {
    void fun(int price, int... discounts) { } // 變長參數
}
class Sub extends Base {
    @Override
    void fun(int price, int[] discounts) { } // 編譯通過,但破壞多態!
}

後果

  • 向上轉型調用 base.fun(100, 50):編譯器將 50 包裝為 new int[]{50},正常執行子類方法。
  • 直接調用 sub.fun(100, 50):編譯器**不**自動包裝,報錯「找不到 fun(int, int) 方法」。

結論:變長參數本質是語法糖,編譯期展開為數組。覆寫時**必須保持變長參數語法**,否則破壞多態調用的一致性。

建議 7:警惕自增(++)的陷阱

經典誤區

int count = 0;
for (int i = 0; i < 10; i++) {
    count = count++; // 以為 count 會加 10
}
System.out.println(count); // 輸出 0!

原理

count++ 是**後綴自增表達式**,其**值**為自增前的值。JVM 執行步驟:

  1. 保存原值到臨時變量 temp = count (0)
  2. count = count + 1 (變為 1)
  3. 表達式結果為 temp (0)
  4. 賦值 count = 0 → 回到初始值

修正:直接寫 count++; 或 count = count + 1;。注意:C++ 中 count = count++ 行為未定義,PHP 與 Java 一致。

建議 8:不要讓舊語法困擾你 —— 標籤語句

public class Client8 {
    public static void main(String[] args) {
        int fee = 200;
        saveDefault: save(fee); // 這是一個標籤 + 調用,非語法錯誤!
    }
    static void saveDefault() { System.out.println("saveDefault"); }
    static void save(int fee) { System.out.println("save: " + fee); }
}
// 輸出:save: 200

saveDefault: 是一個**標籤**,可用於 break saveDefault; / continue saveDefault; 跳出多層循環。此處無循環,標籤無實際作用,純屬干擾閱讀。**避免使用標籤**,現代 Java 通過方法提煉、異常、Stream API 更優雅地控制流程。

建議 9:少用靜態導入

優點

  • 減少類名重複,如 Math.PI → PI,assertEquals 直接調用。

缺點(濫用時)

  • 來源不明:getInstance() 是 NumberFormat 還是本類方法?
  • 命名衝突:多個類導入同名靜態成員,編譯報錯或調用錯誤。
  • 可讀性下降:失去「類名作為命名空間」的語義提示。

原則

  1. 僅對**知名工具類**的**高頻常量/方法**使用:JUnit Assert.*、Math.PI/E、Collections.emptyList()。
  2. **禁用通配符導入**:import static java.lang.Math.*; ❌
  3. 團隊統一風格,Code Review 時強制檢查。

建議 10:不要在本類中覆蓋靜態導入的變量和方法

import static java.lang.Math.PI;
import static java.lang.Math.abs;

public class Client10 {
    public static final String PI = "祖沖之"; // 覆蓋常量
    public static int abs(int x) { return 0; } // 覆蓋方法

    public static void main(String[] args) {
        System.out.println(PI);      // "祖沖之" —— 本類常量勝出
        System.out.println(abs(-100)); // 0 —— 本類方法勝出
    }
}

編譯器「最短路徑」原則:當前類 > 靜態導入 > 父類 > 包導入。本類定義的同名成員**遮蔽**靜態導入成員,導致極難排查的語義錯誤。

最佳實踐:若需修改靜態導入行為,**在原類中重構**,而非在使用方覆蓋。若確需適配,請使用**別名**(Java 無別名機制,可封裝為實例方法調用)。

總結

建議 6-10 圍繞**語法細節陷阱**展開:變長參數覆寫一致性、自增表達式副作用、標籤語句濫用、靜態導入雙刃劍、名稱遮蔽規則。這些看似微小的點,往往是難以復現 Bug 的溫床。將它們內化為編碼肌肉記憶,配合 IDE 檢查、靜態分析,是寫出「不驚艷但不出錯」高質量代碼的關鍵。

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