杰瑞科技汇

Java子类如何调用父类的方法?

super

在 Java 中,super 关键字用于访问和调用父类(超类)的成员,它主要有两个用途:

Java子类如何调用父类的方法?-图1
(图片来源网络,侵删)
  1. 调用父类的构造方法super()super(参数)
  2. 调用父类的成员方法或成员变量super.方法名()super.变量名

我们重点讨论第二种,即调用父类的方法。


调用父类的普通方法(最常用)

当子类重写了(overrode)父类的方法,但又想在该重写的方法中执行父类原来的方法逻辑时,就必须使用 super

场景: 子类扩展了父类的功能,但希望在父类原有功能的基础上增加新的操作。

语法: super.父类方法名(参数列表);

Java子类如何调用父类的方法?-图2
(图片来源网络,侵删)

代码示例:

// 父类
class Animal {
    public void eat() {
        System.out.println("Animal is eating.");
    }
    public void sleep() {
        System.out.println("Animal is sleeping.");
    }
}
// 子类
class Dog extends Animal {
    // Dog 类有自己的 eat() 方法,重写了父类的方法
    @Override
    public void eat() {
        // 首先调用父类原有的 eat() 方法
        super.eat(); 
        // 然后添加 Dog 特有的行为
        System.out.println("Dog is eating bones.");
    }
    // Dog 类想使用父类的 sleep() 方法,可以不重写,直接调用。
    // 但如果想调用,也可以显式使用 super,虽然不常见。
    public void performSleep() {
        super.sleep(); // 显式调用父类的 sleep
    }
}
public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog();
        // 调用 Dog 重写的 eat() 方法
        // 输出:
        // Animal is eating.
        // Dog is eating bones.
        myDog.eat(); 
        // 调用从父类继承来的 sleep() 方法
        // 输出:
        // Animal is sleeping.
        myDog.sleep(); 
        // 调用 performSleep() 方法,它内部使用 super.sleep()
        // 输出:
        // Animal is sleeping.
        myDog.performSleep();
    }
}

分析:Dog 类的 eat() 方法中,我们通过 super.eat() 调用了 Animal 类的 eat() 方法,这允许我们保留父类的核心逻辑,然后在此基础上添加子类特有的行为,这是一种非常常见的代码复用方式。


调用父类的构造方法

这是一个特殊的场景,虽然它不是“方法”,但至关重要,子类在创建对象时,必须先调用父类的构造方法来初始化从父类继承来的成员。

语法: 必须在子类构造方法的第一行使用 super(参数列表); 来调用父类的构造方法。

Java子类如何调用父类的方法?-图3
(图片来源网络,侵删)

如果没有显式调用: 如果子类构造方法中没有 super() 语句,Java 编译器会自动在第一行插入一个对父类无参构造方法 super() 的调用,如果父类没有无参构造方法,就会导致编译错误。

代码示例:

// 父类
class Person {
    private String name;
    // 父类的无参构造方法
    public Person() {
        this.name = "Unknown";
        System.out.println("Person's no-arg constructor is called.");
    }
    // 父类的带参构造方法
    public Person(String name) {
        this.name = name;
        System.out.println("Person's constructor with name is called.");
    }
}
// 子类
class Student extends Person {
    private int studentId;
    // 子类的构造方法1:调用父类的无参构造方法
    public Student() {
        // super(); // 这一行是隐式存在的,可以不写
        System.out.println("Student's no-arg constructor is called.");
    }
    // 子类的构造方法2:调用父类的带参构造方法
    public Student(String name, int studentId) {
        // 必须在第一行显式调用
        super(name); 
        this.studentId = studentId;
        System.out.println("Student's constructor with name and id is called.");
    }
}
public class Main {
    public static void main(String[] args) {
        System.out.println("--- Creating Student with no args ---");
        Student s1 = new Student();
        // 输出:
        // Person's no-arg constructor is called.
        // Student's no-arg constructor is called.
        System.out.println("\n--- Creating Student with args ---");
        Student s2 = new Student("Alice", 101);
        // 输出:
        // Person's constructor with name is called.
        // Student's constructor with name and id is called.
    }
}

特殊情况:不能使用 super 的情况

如果子类没有重写父类的方法,那么子类对象可以直接调用父类的方法,无需使用 super,使用 super 是可以的,但不是必须的。

class Vehicle {
    public void start() {
        System.out.println("Vehicle is starting...");
    }
}
class Car extends Vehicle {
    // Car 没有重写 start() 方法
}
public class Main {
    public static void main(String[] args) {
        Car myCar = new Car();
        // 直接调用,因为 Car 没有自己的 start() 方法
        myCar.start(); // 输出: Vehicle is starting...
        // 使用 super 调用也是可以的,效果一样
        myCar.super.start(); // 语法错误!super 不能用在实例方法中直接这样用
        // 正确的用法是在 Car 的某个方法内部使用 super.start()
    }
}

注意: myCar.super.start() 这种写法是错误的。super 只能在子类的方法内部使用,用来指代父类的版本。


调用场景 语法 说明
子类重写父类方法,并希望调用父类版本 super.父类方法名(); 最常用的场景,用于在扩展功能时保留原有逻辑。
在子类构造方法中初始化父类部分 super(参数列表); 必须在子类构造方法的第一行调用父类的构造方法,如果不写,默认调用 super()
子类直接使用父类未重写的方法 方法名();super.方法名(); 无需 super,直接调用即可,使用 super 是多余的,但语法正确(在方法内部)。

关键点

  1. super 关键字:是连接子类与父类的桥梁。
  2. 方法重写:是使用 super 调用父类方法的主要原因。
  3. 构造方法链super() 在构造方法中的调用是强制性的(隐式或显式),它确保了对象从父类到子类的正确初始化顺序。
  4. 访问权限:只能调用 publicprotected 的父类方法,如果父类方法是 private 的,它对子类是不可见的,也就无法通过 super 调用。
分享:
扫描分享到社交APP
上一篇
下一篇