JAVA中的this和super关键字详解

java中this和super关键字

初学java的同学都知道,this代表当前对象自身,可以看作是当前对象的虚拟地址(尽管不是,当前可以这么理解).后面再做详细讲解.

很多初学java的同学都习惯性的直译super关键字,认为super关键字就是指向当前对象的父类对象的引用.此种想法是错误的,我在JAVA创建子类对象不会实力化父类对象一文中已经提及,当我们实例化子类对象的时候根本就不会创建其父类对象,父类对象都不存在,何来super保存父类对象的虚拟地址一说?

闲言少叙,我们通过下面的例子来看this和super都保存了什么信息:

JAVA中的this和super关键字详解_第1张图片

package test2;

public class Person {
	public Person() {
		System.out.println("Person's this:  " + this);
		//此处如上图所示,不能直接打印super关键字,需要调用下suepr的toString()
		System.out.println("Person's super: " + super.toString());
	}
}


package test2;

public class Teacher extends Person{
	public Teacher() {
		System.out.println("Teacher's this:" + this);
		System.out.println("Teacher's super: " + super.toString());
	}
}	

package test2;

public class Test {
	public static void main(String[] args) {
		Teacher t = new Teacher();
		System.out.println("Teacher对象地址: " + t);
	}
}

我运行了测试类的结果:
JAVA中的this和super关键字详解_第2张图片

通过上面的运行,我们能看到,this和super中存储的都是当前对象在堆中的虚拟地址.下面,我来用图说明下,this和super的具体用法和区别,为了更清晰的认识在创建对象的时候this和super都做了什么,我把代码进行些许改动.

package test2;

public class Person {
	private String name = "无名";
	public Person() {
		super();
		System.out.println("Person's this:  " + this);
		//此处如上图所示,不能直接打印super关键字,需要调用下suepr的toString()
		System.out.println("Person's super: " + super.toString());
		this.name = "王飞";
	}
}

package test2;

public class Teacher extends Person{
	double salary = 8000;
	public Teacher() {
		super();//这里显示调用当前类的父类的无参构造方法,不写的化,虚拟机自动添加。
		System.out.println("Teacher's this: " + this);
		System.out.println("Teacher's super: " + super.toString());
	}
}	

JAVA中的this和super关键字详解_第3张图片
进入debug模式
按F5,启动类加载器
JAVA中的this和super关键字详解_第4张图片
F6:跳过加载器加载过程,回到测试类构造方法
JAVA中的this和super关键字详解_第5张图片

F5:进入Teacher类无参构造方法
JAVA中的this和super关键字详解_第6张图片

JAVA中的this和super关键字详解_第7张图片

F5:执行super(),调用Teacher类的父类的无参构造
JAVA中的this和super关键字详解_第8张图片
Person类无参构造第一行也是调用super()(父类的无参数构造方法),这写和不写都一样,不写的话虚拟机会默认调用父类的无参数构造方法.

JAVA中的this和super关键字详解_第9张图片

F5:执行super(),调用Person类的父类无参构造.

JAVA中的this和super关键字详解_第10张图片
Object类是所有类的"鼻祖"类,只有默认的无参构造,此处不做绘图处理.

F5:返回到Person类,初始化成员变量值(还没进入构造方法的初始值)
JAVA中的this和super关键字详解_第11张图片
在此时,给堆中对象赋值就是根据this关键字进行的赋值(注意,name的值是在this下),也就是说一旦我们new Teacher();
new关键字调用构造方法的时候,就会在堆中创建好对象,并隐式的把对象的首地址值赋予了this关键字.
F5:打印this中保存的值
JAVA中的this和super关键字详解_第12张图片
下面我用堆栈结构演示:
JAVA中的this和super关键字详解_第13张图片
F6:步进,打印super存储的信息
JAVA中的this和super关键字详解_第14张图片
我们会看到在Person类中this关键字和super关键字存储的虚拟地址是同一个虚拟之地,都指向同一个对象
JAVA中的this和super关键字详解_第15张图片
从而把对象中name属性,由null替换成字符串对象"无名".
此处大家可能不太好理解,其本质是现有对象地址,然后根据对象的地址找到堆中的对象,再执行

private String name = “无名”;

这行代码的赋值.如下图:
JAVA中的this和super关键字详解_第16张图片

那么问题来了,既然都是保存同一个地址,那java为什么会分别定义this(当前对象的引用),super(父类""的引用)呢?
在此,我暂且认为super关键字的作用为"域"的标识,是用来标注在堆对象中,哪些属性(成员变量)是从哪个父类(可能还有爷爷类)继承过来的.

为了演示这种效果,我需要在Person类中增加一个可以被子类可见的属性.重构代码

package test2;

public class Person {
	private String name = "无名";
	protected int age;
	public Person() {
		super();
		System.out.println("Person's this:  " + this);
		//此处如上图所示,不能直接打印super关键字,需要调用下suepr的toString()
		System.out.println("Person's super: " + super.toString());
		this.name = "王飞";
		this.age = 37;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

package test2;

public class Teacher extends Person{
	double salary = 8000;
	int age;
	public Teacher() {
		super();//这里显示调用当前类的父类的无参构造方法,不写的化,虚拟机自动添加。
		System.out.println("Teacher's this : " + this);
		System.out.println("Teacher's super: " + super.toString());
		this.age = 39;
		super.age = 38;
	}
	
}	
package test2;

public class Test {
	public static void main(String[] args) {
		Teacher t = new Teacher();
		System.out.println("Teacher对象地址: " + t);
		System.out.println("当父类中有age属性,子类中也有age属性,用当前对象引用看到的是子类的age属性:" + t.age);
	}
}

运行结果:
JAVA中的this和super关键字详解_第17张图片

断点还是在第五行,重新启动debug模式:
JAVA中的this和super关键字详解_第18张图片
F5
JAVA中的this和super关键字详解_第19张图片
F6
JAVA中的this和super关键字详解_第20张图片
F5
JAVA中的this和super关键字详解_第21张图片
F5 调用Teacher类中的super(),即Person类的无参构造方法
JAVA中的this和super关键字详解_第22张图片
F5
JAVA中的this和super关键字详解_第23张图片

F5
JAVA中的this和super关键字详解_第24张图片
F6
JAVA中的this和super关键字详解_第25张图片
F6
JAVA中的this和super关键字详解_第26张图片
F6
JAVA中的this和super关键字详解_第27张图片
JAVA中的this和super关键字详解_第28张图片
this保存堆对象的地址,会通过对象找到堆中对象的name属性进行重新赋值
JAVA中的this和super关键字详解_第29张图片
F6
JAVA中的this和super关键字详解_第30张图片
JAVA中的this和super关键字详解_第31张图片
在此,估计大家会问,你怎确定的上面的age而不是给下面age赋值.这也就是为什么又重构代码的原因.因为虚拟机在加载类的时候,会把当前类有继承关系的类全部加载,并在对象中开辟继承来的属性空间和自身类的属性空间,用"域"做标识
JAVA中的this和super关键字详解_第32张图片
F5
JAVA中的this和super关键字详解_第33张图片

F6
JAVA中的this和super关键字详解_第34张图片
F6
JAVA中的this和super关键字详解_第35张图片
F6
JAVA中的this和super关键字详解_第36张图片
F6
JAVA中的this和super关键字详解_第37张图片
当前执行:this.age = 38; 此时this保存的还是对象地址,但为了大家看的更清晰,我把箭头直接指向了this的"域"
JAVA中的this和super关键字详解_第38张图片

F6
JAVA中的this和super关键字详解_第39张图片
当前执行:super.age = 100; 此时this保存的还是对象地址,但为了大家看的更清晰,我把箭头直接指向了super的"域"
JAVA中的this和super关键字详解_第40张图片
JAVA中的this和super关键字详解_第41张图片
F6
F6
JAVA中的this和super关键字详解_第42张图片
JAVA中的this和super关键字详解_第43张图片

时间比较紧,没办法继续文字说明了,但相信图画的还算清晰,有疑问的朋友可以加我QQ:68370160,共同探讨哈.

你可能感兴趣的:(java基础,java,编程语言)