super关键字和this关键字使用时内存的运行过程

照例先上代码:

public class Fu {
    int num = 10;
    public void method(){
        System.out.println("父类成员方法");
    }
}
public class Zi extends Fu{
    int num = 20;

    @Override
    public void method(){ // 方法名一样,参数列表一样,继承,所以是覆盖重写
        super.method();
        System.out.println("子类成员方法");

    }
    public void show(){
        int num = 30;
        System.out.println(num); // 30 局部变量
        System.out.println(this.num);  // 20 本类成员变量
        System.out.println(super.num); // 10 父类成员变量
    }
}
public class Demo05 {
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.show();
        zi.method();
    }
}

运行截图:

分析内存运行过程:

首先还是按惯常将三个.class信息放入方法区,但是注意因为有了继承关系,在子类的.class信息里有一个编译器自动生成的特殊标记[[super_class]],这个特殊标记是一个指向,指向了父类,告诉子类父类是谁。

然后要运行,那么Demo.class信息里的main方法就要进栈,然后顺序执行main方法里的内容,首先声明一个子类对象,右边赋值new出来的子类对象,则在堆里开辟一块空间存放这个子类对象的信息,并将这个子类对象在堆里的地址值赋值给栈里声明的该对象名。

注意,堆里存放的子类对象当中构建了一个完整的父类结构对象,(所以说,一定是先将父类构造完成了,子类才能继承它构建。)即里边是父外边是子。

我们先看那这个父类结构里有什么东西,有父类里声明的成员变量以及成员方法(注意,这个堆里的成员方法保存的都只是其在方法区的地址值)。

此时各个变量在哪块内存,我们分析清楚了,重点就看this关键字和super关键字。this指代的是调用该方法的对象,所以它应该指代的是子类对象,super指代被子类对象继承的父类对象(因此super关键字也不能用于static方法中,类永远先于对象构建完成)

new出来的子类对象的地址值,赋值给栈中声明的局部变量名,接着又调用一个子类的成员方法show(),根据对象名和.class信息在方法区找到该方法进栈运行(注意方法都要进栈运行),分别输出30,20,10,首先30根据就近原则输出局部变量值,而20调用this关键字,那么就指向指代的子类内容,读取里面的20,进行输出。super关键字也是一样,指向指代的父类内容,读取里面的30,进行输出。

最后运行子类的method方法,优先找到方法区子类的同名方法进栈运行,但是此时注意!子类的这个方法中第一句super.method();运行了父类的同名方法,那么同样由super关键字指代的父类对象查找,父类的同名方法进栈。

然后从栈顶父类method运行,运行完就出栈,运行下一个。

完整内存演化过程图:

猜你喜欢

转载自blog.csdn.net/wardo_l/article/details/113829596
今日推荐