第30章

Java super关键字

理解super关键字的使用场景,掌握访问父类成员和构造方法的技巧

学习目标

super关键字概述

super关键字是Java中用于访问父类成员的重要关键字。它提供了一种明确的方式来引用父类的属性、方法和构造方法,在继承和方法重写中发挥着关键作用。

super关键字的主要用途

  • 调用父类构造方法:使用super()调用父类的构造方法
  • 访问父类方法:使用super.methodName()调用父类方法
  • 访问父类属性:使用super.fieldName访问父类属性

super调用父类构造方法

基本语法

super()用于调用父类的构造方法,必须是子类构造方法的第一条语句。

class Animal {
    protected String name;
    protected int age;
    
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("创建动物: " + name + ", 年龄: " + age);
    }
}

class Dog extends Animal {
    private String breed;
    
    public Dog(String name, int age, String breed) {
        super(name, age);  // 调用父类构造方法
        this.breed = breed;
        System.out.println("创建狗狗,品种: " + breed);
    }
}

重要规则

  • super()必须是构造方法的第一条语句
  • 如果不显式调用super(),编译器会自动插入super()
  • 如果父类没有无参构造方法,子类必须显式调用父类的有参构造方法
  • 不能在静态方法中使用super

super访问父类方法

在方法重写时,可以使用super.methodName()来调用父类的方法,这样可以在保留父类功能的基础上扩展新功能。

class Animal {
    public void eat() {
        System.out.println("动物正在吃东西");
    }
}

class Dog extends Animal {
    @Override
    public void eat() {
        super.eat();  // 调用父类的eat方法
        System.out.println("狗狗喜欢吃骨头和狗粮");
    }
}

使用场景

super访问父类属性

当子类和父类有同名属性时,可以使用super.fieldName来明确访问父类的属性。

class Vehicle {
    protected String type = "交通工具";
}

class Car extends Vehicle {
    private String type = "汽车";
    
    public void showTypes() {
        System.out.println("子类type: " + this.type);    // 汽车
        System.out.println("父类type: " + super.type);   // 交通工具
    }
}

super与this的区别

关键字 作用 示例 使用场景
super 访问父类成员 super.method() 调用父类方法、访问父类属性
this 访问当前类成员 this.method() 访问当前类属性、调用当前类方法
super() 调用父类构造方法 super(param) 子类构造方法中调用父类构造方法
this() 调用当前类其他构造方法 this(param) 构造方法重载时的相互调用

完整代码示例

以下是一个完整的示例,展示了super关键字在实际开发中的应用:

/**
 * super关键字基础示例
 * 演示super关键字的基本用法
 */

class Animal {
    protected String name;
    protected int age;
    
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("创建动物: " + name + ", 年龄: " + age);
    }
    
    public void eat() {
        System.out.println(name + "正在吃东西");
    }
    
    public void showInfo() {
        System.out.println("动物信息 - 名称: " + name + ", 年龄: " + age);
    }
}

class Dog extends Animal {
    private String breed;
    
    public Dog(String name, int age, String breed) {
        super(name, age);  // 调用父类构造方法
        this.breed = breed;
        System.out.println("创建狗狗,品种: " + breed);
    }
    
    @Override
    public void eat() {
        super.eat();  // 调用父类方法
        System.out.println("狗狗喜欢吃骨头和狗粮");
    }
    
    public void bark() {
        System.out.println(super.name + "正在汪汪叫");
    }
    
    @Override
    public void showInfo() {
        super.showInfo();  // 调用父类方法
        System.out.println("品种: " + breed);
    }
}

public class SuperBasicExample {
    public static void main(String[] args) {
        Dog myDog = new Dog("旺财", 3, "金毛");
        
        myDog.eat();
        myDog.bark();
        myDog.showInfo();
    }
}
💻 查看完整代码 - 在线IDE体验

最佳实践

推荐做法

  • 明确性:即使不是必需的,使用super也能提高代码可读性
  • 扩展功能:在重写方法时,先调用super方法,再添加新功能
  • 避免重复:利用super复用父类代码,避免重复实现
  • 构造方法链:合理使用super()建立清晰的构造方法调用链

常见误区

  • 在静态方法中使用super(编译错误)
  • super()不是构造方法的第一条语句
  • 同时使用super()和this()(不允许)
  • 过度使用super导致代码复杂

本章小结