Java super 關鍵字
super 關鍵字用於存取父類別的成員,包括建構子、方法和變數。
呼叫父類別建構子
使用 super() 呼叫父類別的建構子:
class Animal {
protected String name;
public Animal(String name) {
this.name = name;
System.out.println("Animal 建構子");
}
}
class Dog extends Animal {
private String breed;
public Dog(String name, String breed) {
super(name); // 呼叫父類別建構子
this.breed = breed;
System.out.println("Dog 建構子");
}
}
// 使用
Dog dog = new Dog("小黑", "柴犬");
// 輸出:
// Animal 建構子
// Dog 建構子
super() 的規則
- 必須是第一行
public Dog(String name, String breed) {
System.out.println("開始"); // ✗ 編譯錯誤
super(name);
}
- 預設呼叫無參數建構子
如果沒有明確呼叫,編譯器會自動加入 super():
class Animal {
public Animal() {
System.out.println("Animal 預設建構子");
}
}
class Dog extends Animal {
public Dog() {
// 編譯器自動加入 super();
System.out.println("Dog 建構子");
}
}
- 父類別沒有無參數建構子時必須明確呼叫
class Animal {
public Animal(String name) { // 只有這個建構子
this.name = name;
}
}
class Dog extends Animal {
public Dog() {
// 編譯錯誤:父類別沒有無參數建構子
}
public Dog(String name) {
super(name); // ✓ 必須明確呼叫
}
}
存取父類別方法
使用 super.method() 呼叫父類別的方法:
class Animal {
public void speak() {
System.out.println("動物發出聲音");
}
}
class Dog extends Animal {
@Override
public void speak() {
super.speak(); // 先呼叫父類別方法
System.out.println("汪汪!");
}
}
// 使用
Dog dog = new Dog();
dog.speak();
// 輸出:
// 動物發出聲音
// 汪汪!
實際應用:擴展功能
class Logger {
public void log(String message) {
System.out.println("[LOG] " + message);
}
}
class TimestampLogger extends Logger {
@Override
public void log(String message) {
String timestamp = java.time.LocalDateTime.now().toString();
super.log(timestamp + " - " + message); // 加入時間戳記後呼叫父類別方法
}
}
存取父類別變數
當子類別有同名變數時,使用 super.variable 存取父類別變數:
class Parent {
protected String message = "父類別訊息";
}
class Child extends Parent {
private String message = "子類別訊息";
public void show() {
System.out.println(message); // 子類別訊息
System.out.println(this.message); // 子類別訊息
System.out.println(super.message); // 父類別訊息
}
}
注意:變數沒有覆寫的概念,子類別的同名變數會「隱藏」父類別的變數
建構子執行順序
建構子從最上層的父類別開始執行:
class Grandparent {
public Grandparent() {
System.out.println("1. Grandparent 建構子");
}
}
class Parent extends Grandparent {
public Parent() {
System.out.println("2. Parent 建構子");
}
}
class Child extends Parent {
public Child() {
System.out.println("3. Child 建構子");
}
}
// 使用
new Child();
// 輸出:
// 1. Grandparent 建構子
// 2. Parent 建構子
// 3. Child 建構子
super 與 this 的比較
| 特性 | this | super |
|---|---|---|
| 代表 | 當前物件 | 父類別部分 |
| 呼叫建構子 | this() | super() |
| 存取變數 | this.var | super.var |
| 存取方法 | this.method() | super.method() |
| 可省略 | 無衝突時可省略 | 無衝突時可省略 |
不能同時使用
this() 和 super() 不能同時出現在同一個建構子中:
public Dog(String name) {
super(name);
this(); // ✗ 編譯錯誤
}
正確做法是使用建構子鏈:
public Dog() {
this("無名"); // 呼叫另一個建構子
}
public Dog(String name) {
super(name); // 該建構子呼叫父類別
}
多層繼承中的 super
super 只能存取直接父類別:
class A {
protected void methodA() {
System.out.println("A");
}
}
class B extends A {
@Override
protected void methodA() {
System.out.println("B");
}
}
class C extends B {
@Override
protected void methodA() {
super.methodA(); // 呼叫 B 的 methodA()
// super.super.methodA(); // ✗ 無法直接存取 A
}
}
實際範例
員工薪資系統
class Employee {
protected String name;
protected double baseSalary;
public Employee(String name, double baseSalary) {
this.name = name;
this.baseSalary = baseSalary;
}
public double calculateSalary() {
return baseSalary;
}
}
class Manager extends Employee {
private double bonus;
public Manager(String name, double baseSalary, double bonus) {
super(name, baseSalary); // 呼叫父類別建構子
this.bonus = bonus;
}
@Override
public double calculateSalary() {
return super.calculateSalary() + bonus; // 基本薪資 + 獎金
}
}
class SalesEmployee extends Employee {
private double commission;
private int salesCount;
public SalesEmployee(String name, double baseSalary, double commission) {
super(name, baseSalary);
this.commission = commission;
this.salesCount = 0;
}
public void makeSale() {
salesCount++;
}
@Override
public double calculateSalary() {
return super.calculateSalary() + (commission * salesCount);
}
}
GUI 元件
class Component {
protected int x, y, width, height;
public Component(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public void draw() {
System.out.println("繪製元件於 (" + x + ", " + y + ")");
}
}
class Button extends Component {
private String label;
public Button(int x, int y, int width, int height, String label) {
super(x, y, width, height);
this.label = label;
}
@Override
public void draw() {
super.draw(); // 先執行父類別的繪製
System.out.println("繪製按鈕文字:" + label);
}
}
super 不能用的情況
靜態方法中不能使用
class Parent {
protected int value = 10;
}
class Child extends Parent {
public static void staticMethod() {
// System.out.println(super.value); // ✗ 編譯錯誤
}
}
最頂層類別
Object 是所有類別的根,沒有父類別:
class MyClass {
public void method() {
super.toString(); // ✓ 呼叫 Object.toString()
// super.super... // 不存在更上層
}
}
重點整理
super()呼叫父類別建構子,必須是第一行super.method()呼叫父類別的方法super.variable存取父類別的變數- 建構子從最上層父類別開始執行
this()和super()不能同時使用super只能存取直接父類別- 靜態方法中不能使用
super