super、static、final 是 Java 面向對象編程的三大基石關鍵字,掌握其語義、約束與最佳實踐,是寫出清晰、健壯代碼的前提。本文通過代碼示例與對比表格,系統講解三者的核心用法與易混淆點。
| 用法 | 語法 | 規則 | 示例 |
|---|---|---|---|
| 調用父類構造方法 | super(參數列表) | 必須放在子類構造方法第一行;若未顯式調用,隱式調用 super() | public Child(String name) { super(name); } |
| 訪問父類屬性 | super.屬性名 | 子類與父類同名屬性時,區分訪問 | super.name = "parent"; |
| 調用父類方法 | super.方法名(參數) | 方法被覆寫時,調用父類版本;常用於擴展而非完全替換 | @Override public String toString() { return super.toString() + ", child"; } |
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getInfo() {
return "姓名:" + name + ";年齡:" + age;
}
}
class Student extends Person {
private String school;
public Student(String name, int age, String school) {
super(name, age); // 必須第一行調用父類構造
this.school = school;
}
@Override
public String getInfo() {
return super.getInfo() + ";學校:" + school; // 擴展父類邏輯
}
}
public class Demo {
public static void main(String[] args) {
Student stu = new Student("李四", 25, "北京大學");
System.out.println(stu.getInfo());
// 輸出:姓名:李四;年齡:25;學校:北京大學
}
}
| 維度 | this | super |
|---|---|---|
| 屬性訪問 | 本類屬性 → 父類屬性 | 直接訪問父類屬性 |
| 方法調用 | 本類方法 → 父類方法 | 直接調用父類方法 |
| 構造調用 | this(...) 調用本類其他構造 | super(...) 調用父類構造 |
| 特殊含義 | 當前對象引用 | 無對象引用概念 |
| 共同約束 | 構造調用必須放在首行,不可同時出現 | |
關鍵規則:無論子類如何操作,父類構造方法總是最先執行,保證父類部分正確初始化。
this 引用,只能訪問靜態成員// 推薦:類名訪問
MyClass.staticField = 10;
MyClass.staticMethod();
// 不推薦但合法:實例訪問(編譯器會轉為類名訪問)
MyClass obj = new MyClass();
obj.staticField = 20; // 警告:靜態成員應通過類名訪問
this、super 關鍵字1. 父類靜態變量/靜態代碼塊(按聲明順序) 2. 子類靜態變量/靜態代碼塊(按聲明順序) 3. 父類實例變量/實例代碼塊 4. 父類構造方法 5. 子類實例變量/實例代碼塊 6. 子類構造方法
| 修飾目標 | 語義 | 核心規則 | 典型場景 |
|---|---|---|---|
| 類 | 不可繼承 | 不能有子類;隱含所有方法 final | String、Integer、工具類 |
| 方法 | 不可覆寫 | 子類不可 override;private 方法隱式 final | 模板方法模式固定骨架、安全敏感方法 |
| 變量(基本類型) | 不可修改值 | 編譯期常量折疊;引用賦值後不可變 | 常量定義、配置參數 |
| 變量(引用類型) | 引用不可變 | 指向對象不變,但對象內部狀態可變 | 集合引用、對象引用 |
| 參數 | 方法內不可重賦值 | 不影響調用端變量(值傳遞) | 防止誤修改參數引用 |
// 類常量:全大寫,下劃線分隔
public static final int MAX_CONNECTIONS = 100;
public static final String DEFAULT_ENCODING = "UTF-8";
// 實例常量:構造方法/實例代碼塊初始化
public final String instanceId; // 必須在構造方法中賦值
final List<String> list = new ArrayList<>();
list.add("hello"); // ✅ 合法:修改對象內部狀態
list = new ArrayList<>(); // ❌ 編譯錯誤:修改引用指向
本質:final 保護的是引用地址不變,而非對象內容不可變。真正不可變對象需結合不可變集合(Collections.unmodifiableList)或自定義不可變類實現。
public final class Constants { // final 類,防繼承
// 編譯期常量,內聯優化
public static final int DEFAULT_PORT = 8080;
public static final String VERSION = "1.0.0";
// 靜態初始化塊,複雜常量初始化
public static final Map<String, String> ERROR_CODES;
static {
Map<String, String> map = new HashMap<>();
map.put("404", "Not Found");
map.put("500", "Internal Error");
ERROR_CODES = Collections.unmodifiableMap(map); // 防篡改
}
// 私有構造,防實例化
private Constants() {}
}
public abstract class BaseService {
// 模板方法:final 鎖定骨架,子類實現具體步驟
public final void process(Request req) {
validate(req);
doProcess(req);
log(req);
}
protected abstract void doProcess(Request req); // 子類必須實現
private void validate(Request req) { ... }
private void log(Request req) { ... }
}