這一節我們來講一個關鍵字,就是this關鍵字。
我們還是通過例子來看吧:
~~~
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給我們解決方案,那就是用一個關鍵字this來區分成員變量和局部變量。我們再來改造:
~~~
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方法出棧,程序運行結束。
通過上面的過程分析,我們可以簡單的總結出這樣一個結論:當在函數中需要用到調用函數的對象時,就用this關鍵字。
為了更好的理解這個結論,我們把上面的例子可以標準的寫成下面這樣:
~~~
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是可以省略的,但請注意,不是沒有,而是省略。
- 前言
- 1.1 基本常識
- 1.2 Java語言概述
- 1.3 Java語言的環境搭建
- 1.4 Java程序開發之初體驗--Hello World
- 2.1 關鍵字
- 2.2 標識符
- 2.3 注釋
- 2.4 常量
- 2.5 進制掃盲
- 2.6 變量和數據類型(1)
- 2.7 變量和數據類型(2)
- 2.8 運算符
- 3.1 if語句
- 3.2 switch語句
- 3.3 while和do-while語句
- 3.4 for語句
- 3.5 for循環的嵌套
- 3.6 break語句與continue語句
- 4.1 函數的定義
- 4.2 定義函數的兩個明確
- 4.3 函數的內存加載過程
- 4.4 函數的重載
- 5.1 數組的定義
- 5.2 數組的內存分配及特點
- 5.3 數組操作中常見問題
- 5.4 數組常用操作(1)
- 5.5 數組常用操作(2)
- 5.6 二維數組
- 6.1 面向對象的概述
- 6.2 類與對象的關系
- 6.3 對象的內存體現
- 6.4 成員變量與局部變量
- 6.5 類類型參數與匿名對象
- 6.6 基本數據類型參數與引用數據類型參數的傳遞過程
- 6.7 封裝
- 7.1 構造函數概述與默認構造函數
- 7.2 構造函數與一般函數的區別
- 7.3 構造函數的重載
- 7.4 構造函數的內存加載
- 7.5 構造函數需要注意的幾個細節
- 7.6 this關鍵字的原理
- 7.7 this關鍵字的細節與應用
- 8.1 static關鍵字之特點
- 8.2 成員變量與靜態變量的區別
- 8.3 static關鍵字使用的注意細節
- 8.4 main函數的解析與細節
- 8.5 static關鍵字的使用場景
- 8.6 靜態的內存加載
- 8.7 靜態代碼塊
- 8.8 構造代碼塊
- 9.1 繼承
- 9.2 單繼承與多重繼承
- 9.3 子父類中成員變量特征體現