繼承是在現有類型基礎上,通過添加新方法或重新定義現有方法產生新類型。Java 中三種類型:
class 定義、無抽象方法abstract class、可含抽象方法interface、默認 public abstract 方法| 子類型 \ 父類型 | 類 | 抽象類 | 接口 |
|---|---|---|---|
| 類 | extends(單繼承) | extends(單繼承) | implements(多實現) |
| 抽象類 | extends | extends | implements |
| 接口 | ✗ | ✗ | extends(多繼承) |
public class Sub {
private Parent parent = new Parent(); // 或延遲初始化
public void doSomething() {
parent.method(); // 復用父類功能
}
}
適用於「has-a」關係,避免繼承帶來的強耦合、脆弱基類問題。
| 類型 | 別名 | 時機 | 適用方法 |
|---|---|---|---|
| 早期綁定 | 靜態綁定 | 編譯/鏈接期 | static、final、private、構造器 |
| 晚期綁定 | 動態綁定 | 運行期 | 其他實例方法(虛方法) |
interface Car {
String getName();
int getPrice();
}
class BMW implements Car {
public String getName() { return "BMW"; }
public int getPrice() { return 300000; }
}
class CheryQQ implements Car {
public String getName() { return "CheryQQ"; }
public int getPrice() { return 20000; }
}
class CarShop {
private int total = 0;
public void sellCar(Car car) { // 多態參數
System.out.println("車型: " + car.getName() + " 價格: " + car.getPrice());
total += car.getPrice();
}
public int getTotal() { return total; }
}
// 新增車型零修改 CarShop
class Santana implements Car {
public String getName() { return "Santana"; }
public int getPrice() { return 80000; }
}
簽名 = 方法名 + 參數列表(數量、類型、順序)。不包含:返回類型、訪問修飾符、abstract/static/final 等修飾符。
| 特性 | 重載 | 重寫 |
|---|---|---|
| 位置 | 同一類 | 父子類 |
| 方法名 | 相同 | 相同 |
| 參數列表 | 不同 | 相同 |
| 返回類型 | 可不同 | 兼容(协变返回) |
| 訪問權限 | 無限制 | 不能減弱 |
| 拋出異常 | 無限制 | 不能擴大 |
| 綁定時機 | 編譯期 | 運行期 |
| 多態相關 | 無關 | 核心基礎 |
class Base { public: void fun() {} void fun(int i) {} };
class Derive : public Base { public: void fun(int i, int j) {} }; // 隱藏基類所有 fun 重載版本
Derive d;
d.fun(1,2); // OK
d.fun(); // 編譯錯誤:基類 fun() 被隱藏
d.fun(1); // 編譯錯誤:基類 fun(int) 被隱藏
解決:using Base::fun; 在派生類引入基類名字空間。
String s = "abc":池中查找,有則返回引用,無則創建入池new String("abc"):堆中創建新對象,值共享池中 char 數組String str = new String("abc"); // 創建幾個對象?
// 答案:2 個
// 1. "abc" 字面量 → 常量池(若不存在)
// 2. new String(...) → 堆中新對象
| 表達式 | 結果 | 進池 |
|---|---|---|
"ab" + "cd" | "abcd" | 是(編譯期常量折疊) |
String a = "ab"; a + "cd" | "abcd" | 否(運行期 new StringBuilder) |
final String A = "ab"; final String B = "cd"; A + B | "abcd" | 是(編譯期常量) |
static final String A; static { A="ab"; } A + "cd" | "abcd" | 否(運行期賦值) |
String a = new String(new char[]{'a','b','c','d'});
String b = a.intern(); // 池中查找,有則返回池引用,無則創建入池並返回
// b != a(除非池中原本就有相同值)
繼承、多態、重載、重寫構成 Java 面向對象核心。繼承建立類型層級,重寫實現行為多樣性,多態實現運行時動態分發,重載提供編譯期便利。理解 C++ 隱藏/覆蓋機制有助於深度掌握多態本質。String 池機制體現「享元模式」優化內存,掌握字面量 vs new、常量折疊、intern() 行為差異,是避免生產 Bug 的關鍵。