zl程序教程

您现在的位置是:首页 >  工具

当前栏目

[javase学习笔记]-7.6 thiskeyword的原理

2023-09-11 14:20:46 时间

这一节我们来讲一个keyword。就是thiskeyword。

我们还是通过样例来看吧:

class Person
{
	private String name;
	private int age;

	Person(String n,int a)
	{
		name = n;
		age = a;
	}

	public void speak()
	{
		System.out.println(name+":"+age);
	}
}
class ThisTest 
{
	public static void main(String[] args) 
	{
		Person kobe = new Person("KOBE",37);
		kobe.speak();
	}
}
这个样例我们应该非常熟悉了,前面几节都在用这个样例。我们再来看一看结果:

非常显然,构造函数对对象kobe进行了初始化。

可是我们发现,尽管结果是我们想要的,可是,我们单独看这个构造函数,从可读性的角度我们分析,我们根本就不知道函数传过来的是什么内容,我们能够说一无所知。可阅读性太差了,那么我们再对这个构造函数进行改造:

class Person
{
	private String name;
	private int age;

	Person(String name,int age)
	{
		name = name;
		age = age;
	}

	public void speak()
	{
		System.out.println(name+":"+age);
	}
}
唉。这样不是非常清晰了吗。我们一眼就看出这个构造函数要告诉我们初始化对象的姓名和年龄了。我们看结果:

嗯???这是什嘛情况,KOBE人呢?

我们7.4节谈过了构造函数的内存载入过程,可是我们没有提到这里遇到的这样的情况。这样的情况我们能够说是:成员变量和局部变量重名的问题,此时对于栈内存和堆内存中都会变量name和age,而调用的构造函数会自己主动到栈内存中寻找这两个变量。而此时。恰好都有,所以系统就会做一个很有趣的事情。就是把栈内存中的name原赋给本身。而对象的name和age的值事实上在堆内存中,所以结果就是我们刚才看到的结果喽。

那么对于这个问题,我们该怎么解决呢?

java给我们解决方式。那就是用一个keywordthis来区分成员变量和局部变量。我们再来改造:

class Person
{
	private String name;
	private int age;

	Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}

	public void speak()
	{
		System.out.println(name+":"+age);
	}
}
结果:

非常好,KOBE同志又回来了。

所以我们能够说。当成员变量与局部变量重名时,我们能够用this来区分。

那么我们就想明确,this究竟代表什么呢?java语言说,this代表的是对象。

我们还想明确,this代表的是哪个对象?java语言又说,代表的就是当前对象。

专业点的术语是这样定义this的:this就是所在函数所在对象的引用。说简单点就是:this代表本类对象的引用。

我们自己用通俗点的语言来定义:就是哪个对象调用了this所在的哪个函数,this就代表哪个对象,也就是说this就是这个对象的引用。

比方上面的样例中的kobe调用了构造函数Person(String name,int age),那么我们可说this就能够代表kobe这个对象。


那么我们再来对this在内存中的体现过程分析一下,我们继续7.4的过程,仅仅有小的变动。

1.main方法进栈内存。main方法中有一个Person类类型变量kobe;

2.new创建Person对象,在堆内存中创建空间(假如地址为0x0045)。该空间中有两个成员变量name和age;

3.对对象的两个成员变量进行初始化,此时会自己主动选择调用构造函数Person(String n,int a);

4.构造函数Person(String name,int age)进栈内存,參数name="KOBE",age=0也载入入栈。

而此时系统会自己主动为该栈内存中载入一个对象的引用,也就是this,而且把kobe的堆内存地址赋给this;

5.然后在把this.name和this.age的初始化为栈内存中name和age,这样就非常清晰了。this.name和this.age我们能够理解为就this所指堆内存中对象的成员变量,此时对象的初始化完毕;

6.把地址0x0045赋给main方法中的实例变量kobe;

7.构造函数Person(String name,int age)出栈,释放參数name和age和this引用;

8.运行kobe.speak()语句。调用Person类中的speak()方法。则speak方法进栈,此时系统也会为speak方法载入一个this引用,指向堆内存中的对象地址(0x0045);

9.运行打印语句,跳出speak方法,speak方法出栈。释放this引用;

10.跳出main方法,main方法出栈,程序执行结束。

通过上面的过程分析,我们能够简单的总结出这样一个结论:当在函数中须要用到调用函数的对象时。就用thiskeyword。

为了更好的理解这个结论,我们把上面的样例能够标准的写成以下这样:

class Person
{
	private String name;
	private int age;

	Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}

	public void speak()
	{
		System.out.println(this.name+":"+this.age);
	}
}
我们对这个类方法中的全部成员变量都标准的写成了this.成员变量的格式。

那么我们刚開始看的第一个样例为什么没有this,而结果是也是正确的呢?

非常显然,当然对于成员变量与局部变量不重名时。this是能够省略的,但请注意,不是没有,而是省略。