Java学习9:super(隐式参数)关键字内存分析详解及用法

super关键字,是一个隐式参数(另一个隐式参数是this)。


注:super关键字和this关键字极为类似,学习时可参考this关键字用法。this(隐式参数)关键字内存分析详解及用法

1.概述

super是直接父类的引用(this是当前对象的引用)。可以通过super来访问父类中被子类覆盖的方法或属性。

  • super关键字,是一个隐式参数,另外一个隐式参数是this。
    super用于方法里面,用于方法外面无意义。
  • super关键字一般用于继承和构造方法中。
  • 任何类的构造函数中,若是构造函数的第一行代码没有显式的调用super(),那么Java默认都会调用super();作为父类的初始化函数。所以这里的super()加不加都无所谓 。

下面从内存分析的角度去理解super关键字,然后关注其常见用法。

2.super关键字内存分析

2.1分析代码

首先创建一个Bird类,及其直接父类Animal类,并分别创建其构造方法:

public class Animal {
    String name;

    public Animal() {
    }

    void eat() {
        System.out.println("have a good dinner");
    }
}

class Birds extends Animal {

    public Birds() {
    }

    @Override
    void eat() {
        super.eat(); // 调用父类的方法
        System.out.println("----------------------------------------"); // 分隔线
        System.out.println("jiujiujiu");
    }

    void fly() {
        System.out.println("Yeah,I can fly~~");
    }
}

2.2代码分析

在上述代码中,我们并没有看到super关键字,事实上,在两个构造器中,均有super(),其实该段代码也可以写成:

public class Animal {
    String name;

    public Animal() {
        super(); // 调用父类Object构造器
    }

    void eat() {
        System.out.println("have a good dinner");
    }
}

class Birds extends Animal {

    public Birds() {
        super(); // 调用父类Animal构造器
    }

    @Override
    void eat() {
        super.eat(); // 调用父类的方法
        System.out.println("----------------------------------------"); // 分隔线
        System.out.println("jiujiujiu");
    }

    void fly() {
        System.out.println("Yeah,I can fly~~");
    }
}

可以看出,构造器中通过super()调用直接父类的构造器。明白了这一点,就可以进行接下来的内存分析。

2.3内存分析

接下来我们进行内存分析,并绘制内存分析图。
首先我们创建一个测试类Test类,并声称一个Birds对象,如下:

class Test {
    public static void main(String[] args) {
        Birds b = new Birds();
        b.eat();
    }
}

2.3.2Test类调用main方法

2.3.3Birds b = new Birds();调用Birds构造器

这一步是最重要的,也是重点分析。
1. 当调用Birds类的构造器Birds()时,里面的第一行代码super()(无论是否显式写出,都存在),回去寻找Birds类的直接父类,并且Birds构造器停留在此,不会往下执行。
2. 然后找到Animal构造器,并且同样有super()方法,回去寻找Animal的直接父类,也就是基类Object。
3. 然后执行Object类的构造器,这里Object时所有类的基类,他并没有直接父类。
4. 根据Object类的代码信息,生成第一个Object对象。
5. 此时Animal中的super()已经执行完成,并接着往下执行,完成了Animal构造器的全部加载,并生成一个Animal对象。
6. 同样的,Birds中的super()也执行完成。并完成Birds构造器的全部,生成一个Birds对象。

至此,该段代码加载完成。如下图:
这里写图片描述

b.eat();

eat()override了父类Animal的方法,我们这里通过b智能调用Birds中的eat(),但是从图中我们可以看到父类Animal中的eat()方法仍然存在,那我们怎么使用呢。
答案很简单,我们可以在Birds类中的eat()中调用父类的该方法,如下:

    @Override
    void eat() {
        super.eat(); // 调用父类的方法
        System.out.println("----------------------------------------"); // 分隔线
        System.out.println("jiujiujiu");
    }

因而,在普通方法中,可以随意通过super调用父类的被override的方法。所以在方法中均存在两个隐式参数,一个是this,一个super

3.一个有意思的小问题

之前我们提到,super()其实位于构造器的第一行,如果放在其他行会报错,如下:

    public Birds() {
        System.out.println("sss");
        super();
    }

报错信息:

Constructor call must be the first statement in a constructor

构造器的调用必须放在构造器的首句

这句话很熟悉,我们在学习this关键字中也遇到过这句话,我们知道,可以通过this()调用重载的构造器。那么我们可以同时使用super()和this()吗?
首先我们知道,如果在构造器中使用this(),那么必须具有至少两个构造器。如下:

    public Birds() {
        super();
    }

    public Birds(String name) {
        this();
    }

我们尝试在含参的构造器中使用super():

    public Birds(String name) {
        this();
        super();
    }

super()报错:Constructor call must be the first statement in a constructor

换一个顺序:

    public Birds(String name) {
        super();
        this();
    }

this()报错:Constructor call must be the first statement in a constructor
无论怎样,两个都必须位于第一行,因而super()和this()不同出现在同一个构造器中


其实这个情况,也会出现在两个this的情况中,一个Birds(int num,String name)想要同时调用两个构造器Birds()和Birds(String name),也会出现该种情况。如下第二句是会报错的:

    public Birds(int num, String name) {
        this();
        this("niao");
    }

Constructor call must be the first statement in a constructor
如果我们想要完成类似的调用,可以这么写:

    public Birds() {
        super();
    }

    public Birds(String name) {
        this();
    }

    public Birds(int num, String name) {
        this("niao");
    }

结论很简单,一个构造器,只能直接调用一个构造器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值