【Java基础】Java 中的 super 关键字

前言

在 Java 的面向对象编程中,继承是一个核心特性,它允许我们创建一个新类(子类)来继承另一个已有类(父类)的属性和方法。而 super 关键字则是在这个继承体系中扮演着至关重要的角色,它为子类与父类之间的交互提供了强大的支持。

1. super 关键字的基本概念

super 关键字是 Java 中的一个引用变量,它指向当前对象的父类对象。通过 super,子类可以访问父类的成员,包括成员变量、方法和构造器。在子类中,当子类的成员与父类的成员重名时,使用 super 关键字可以明确指定要访问的是父类的成员。

2. 使用 super 访问父类的成员变量

成员变量的隐藏问题

在 Java 中,如果子类定义了一个与父类同名的成员变量,那么子类的成员变量会隐藏父类的成员变量。此时,如果子类需要访问父类的同名成员变量,就可以使用 super 关键字。

示例代码

class Parent {
    int value = 10;
}

class Child extends Parent {
    int value = 20;

    public void printValues() {
        // 访问子类的成员变量
        System.out.println("Child's value: " + this.value); 
        // 访问父类的成员变量
        System.out.println("Parent's value: " + super.value); 
    }
}

public class Main {
    public static void main(String[] args) {
        Child child = new Child();
        child.printValues();
    }
}

代码解释

在上述代码中,Parent 类和 Child 类都定义了一个名为 value 的成员变量。在 Child 类的 printValues 方法中,this.value 访问的是子类的 value 变量,而 super.value 访问的是父类的 value 变量。运行这段代码,输出结果如下:

Child's value: 20
Parent's value: 10

3. 使用 super 调用父类的方法

方法的重写与父类方法调用

当子类重写了父类的方法时,如果子类需要在重写的方法中调用父类的原始方法,可以使用 super 关键字。这在需要对父类方法进行扩展时非常有用。

示例代码

class Animal {
    public void makeSound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        // 调用父类的 makeSound 方法
        super.makeSound(); 
        System.out.println("Dog barks");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.makeSound();
    }
}

代码解释

在这个例子中,Animal 类有一个 makeSound 方法,Dog 类重写了这个方法。在 Dog 类的 makeSound 方法中,使用 super.makeSound() 调用了父类的 makeSound 方法,然后再输出自己的信息。运行代码,输出结果为:

Animal makes a sound
Dog barks

4. 使用 super 调用父类的构造器

构造器的继承规则

在 Java 中,子类不会继承父类的构造器,但子类的构造器可以通过 super 关键字调用父类的构造器。这是因为在创建子类对象时,父类的部分需要先进行初始化。如果子类的构造器中没有显式调用父类的构造器,Java 编译器会自动在子类构造器的第一行插入 super() 语句,调用父类的无参构造器。

示例代码

class Vehicle {
    protected String brand;

    public Vehicle(String brand) {
        this.brand = brand;
    }
}

class Car extends Vehicle {
    private int numberOfDoors;

    public Car(String brand, int numberOfDoors) {
        // 调用父类的构造器
        super(brand); 
        this.numberOfDoors = numberOfDoors;
    }

    public void displayInfo() {
        System.out.println("Brand: " + brand + ", Number of doors: " + numberOfDoors);
    }
}

public class Main {
    public static void main(String[] args) {
        Car car = new Car("Toyota", 4);
        car.displayInfo();
    }
}

代码解释

Car 类的构造器中,使用 super(brand) 调用了父类 Vehicle 的有参构造器,将 brand 参数传递给父类进行初始化。然后再对 Car 类自身的成员变量 numberOfDoors 进行初始化。运行代码,输出结果为:

Brand: Toyota, Number of doors: 4

注意事项

  • 调用位置super()super(参数列表) 必须放在子类构造器的第一行,否则会编译错误。这是为了确保父类的初始化工作在子类初始化之前完成。
  • 父类无参构造器缺失问题:如果父类没有无参构造器,而子类的构造器中又没有显式调用父类的有参构造器,编译器会报错。因此,当父类只有有参构造器时,子类的构造器必须显式调用父类的有参构造器。

5. super 在多层继承中的应用

多层继承结构

在 Java 中,继承可以形成多层结构,即一个子类可以有自己的子类。在这种多层继承结构中,super 关键字同样可以发挥作用,帮助我们在不同层次的子类中访问父类的成员。

示例代码

class GrandParent {
    void display() {
        System.out.println("GrandParent's display method");
    }
}

class Parent extends GrandParent {
    @Override
    void display() {
        // 调用祖父类的 display 方法
        super.display(); 
        System.out.println("Parent's display method");
    }
}

class Child extends Parent {
    @Override
    void display() {
        // 调用父类的 display 方法
        super.display(); 
        System.out.println("Child's display method");
    }
}

public class Main {
    public static void main(String[] args) {
        Child child = new Child();
        child.display();
    }
}

代码解释

在这个多层继承的例子中,Child 类继承自 Parent 类,Parent 类继承自 GrandParent 类。在 Child 类的 display 方法中,使用 super.display() 调用了父类 Parentdisplay 方法;在 Parent 类的 display 方法中,使用 super.display() 调用了祖父类 GrandParentdisplay 方法。运行代码,输出结果为:

GrandParent's display method
Parent's display method
Child's display method

6. 对比 thissuper 关键字

相似之处

  • thissuper 都是 Java 中的引用变量,用于引用对象。
  • 它们都可以在构造器和方法中使用。

不同之处

  • 引用对象不同this 指向当前对象本身,而 super 指向当前对象的父类对象。
  • 用途不同this 主要用于区分成员变量和局部变量、在构造器中调用本类的其他构造器、返回当前对象的引用等;而 super 主要用于访问父类的成员变量、调用父类的方法和构造器。

总结

super 关键字在 Java 的继承体系中扮演着不可或缺的角色,它为子类与父类之间的交互提供了便捷的方式。通过 super,我们可以访问父类的成员变量、调用父类的方法和构造器,从而实现代码的复用和扩展。

你可能感兴趣的:(Java,java,开发语言)