天天看点

Java - 内存分析:super 与 this一、绘制内存结构图二、类加载三、对象实例化四、调用对象方法

内存分析:super 与 this

  • 一、绘制内存结构图
  • 二、类加载
  • 三、对象实例化
  • 四、调用对象方法

根据以下父子类的定义调用代码,分析super与this关键字在内存中的执行过程

class Fu {
	int num = 10;
	public void method() {} 	// 父类方法
}

class Zi extends Fu {
	int num = 20;
	public void method() {}		// 子类重写父类方法
	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 Demo {
	public static void main(String[] args) {
		Zi zi = new Zi();
		zi.show();
		zi.method();
	}
}
           

一、绘制内存结构图

Java - 内存分析:super 与 this一、绘制内存结构图二、类加载三、对象实例化四、调用对象方法

二、类加载

Fu类、Zi类、Demo类的字节码依次被加载到方法区。不同的是,子类在加载过程中会有一个 [[super_class]] 标记,这个标记指向父类,表示子类继承自父类

Java - 内存分析:super 与 this一、绘制内存结构图二、类加载三、对象实例化四、调用对象方法

三、对象实例化

栈中开辟main方法栈帧,内部开辟名为zi的Zi类型变量,堆中实例化一个Zi类对象,由于Zi类是继承自Fu类的,实例化的Zi类对象内部会包含一个完整的Fu类对象,Fu类内容与Zi类内容之间相互隔离。JVM使用this指针指向子类内容,使用super指针指向父类内容。最后,将Zi类对象的地址赋值给栈空间的zi变量

Java - 内存分析:super 与 this一、绘制内存结构图二、类加载三、对象实例化四、调用对象方法

四、调用对象方法

Zi类中的show()方法栈帧压栈,并在栈帧中定义一个num变量,进而依次执行:

  1. 打印方法本身栈帧中局部变量,根据this指针找到自身的成员变量并打印,
  2. 根据super指针找到Fu类的成员变量并打印。
  3. 最后,show()方法执行完毕,弹栈。
    Java - 内存分析:super 与 this一、绘制内存结构图二、类加载三、对象实例化四、调用对象方法
  1. 在Zi类的成员方法中找到Zi类的 method() 方法在方法区内的地址,将Zi类 method() 方法压栈
  2. 执行Zi类method方法时,内部有一个 super.method() 语句,根据super指针找到父类,在父类的成员方法中找到Fu类的method()方法在方法区中的地址,将Fu类method方法压栈
  3. Fu类method方法执行完毕后弹栈,回到Zi类method方法继续执行完毕后弹栈,
  1. 程序最后回到main方法继续执行完毕后弹栈,程序执行结束
Java - 内存分析:super 与 this一、绘制内存结构图二、类加载三、对象实例化四、调用对象方法

图片内容源自B站黑马Java基础公开课