照例先上代码:
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运行,运行完就出栈,运行下一个。
完整内存演化过程图:

本文通过一个Java代码示例分析了继承关系下内存的运行过程,详细解释了对象创建、成员变量、this与super关键字的使用,以及方法的调用顺序。在内存中,子类对象包含了完整的父类结构,成员方法作为引用存储在方法区,this指代子类对象,super则指向父类对象。代码执行过程中,方法按栈的运行机制进行,展示了this与super在不同情境下的作用。

被折叠的 条评论
为什么被折叠?



