天天看點

java this關鍵字的使用_Java語言this關鍵字用法全面總結

java this關鍵字的使用_Java語言this關鍵字用法全面總結

學習Java程式設計的時候,無論是誰,當學到面向對象這部分内容時都會遇到一個關鍵字:this。很多初學者對這個關鍵字的都會感覺到了解不透,不明白這個神秘的”this”到底表示什麼意思。按照官方正規的解釋,this關鍵字的意義被解釋為“指向目前對象的引用”。這個解釋非常準确并且很精煉,但它太過學術化了,導緻很多初學者有點讀不懂,更談不上深入了解它的意義。本文将用大白話的形式幫助初學Java的小夥伴來深入了解this關鍵字的意義,并且梳理它的各種用法。

其實,我們隻要把this了解成”本對象自己的...”就可以了。看到這個解釋,很多人可能更懵了,什麼叫”本對象自己的...”?不要着急,讓我們首先來看一段代碼。

java this關鍵字的使用_Java語言this關鍵字用法全面總結

在這段代碼中,定義了一個表示”人”的類Person,在Person類中,有3個屬性name、age和height,分别來表示姓名、年齡和身高。在類當中定義了一個構造方法,構造方法中對3個屬性進行了初始化操作。最後定義了一個introduce方法,這個方法能夠列印一個Person對象的姓名和年齡。現在,我們在main方法當中建立一個Person類的對象,并且調用這個對象的introduce方法,代碼如下:

java this關鍵字的使用_Java語言this關鍵字用法全面總結

愉快的運作一下程式,出來的運作結果是這樣的:

java this關鍵字的使用_Java語言this關鍵字用法全面總結

通過程式的運作結果我們可以看出,在建立對象的時候,對象的屬性被賦予了正确初始值。這個程式本身非常的簡單,誰都可以了解,但是大家請注意,我們在定義構造方法的時候,把表示姓名、年齡和身高的參數分别命名為:n、a和h,這種命名的可讀性有點差,為了提高可讀性,我們把構造方法的參數名稱修改為name、age和height,如下圖所示:

java this關鍵字的使用_Java語言this關鍵字用法全面總結

修改之後,再次運作main方法,得到的運作結果變成了這個樣子:

java this關鍵字的使用_Java語言this關鍵字用法全面總結

為什麼這一次的運作結果出現了問題呢?就是因為,修改了構造方法之後,當我們調用構造方法建立對象時,給構造方法所傳遞的3個參數值“張三”、20和178.5最終并沒有指派到對象的3個屬性中。那麼,既然參數值沒有被指派到對象的屬性中,它們去了哪裡呢?修改代碼後,構造方法的參數與類所定義的屬性同名,根據”同名情況下,局部變量的優先級更高”原則,在構造方法執行的過程中,虛拟機會把參數值賦給”參數本身”,而不是指派給對象的屬性!具體來說,就是我們給構造方法的name參數傳遞的值是”張三”,而這個”張三”在構造方法執行的過程中,當運作到”name=name;”這條語句時,并沒有把”張三”指派給對象的name屬性,而是又重新指派給了name參數自身。就是因為”張三”最終沒有被指派到對象的name屬性中,才導緻introduce方法中列印出的name屬性是null。當然,age和height這兩個參數也是同樣的指派效果。

為了能夠讓虛拟機明白我們所期望的是:把”張三”這個字元串指派給對象的name屬性,而不是”再一次”把它指派給構造方法的參數,就需要把構造方法中的指派語句做出如下修改:

java this關鍵字的使用_Java語言this關鍵字用法全面總結

大家來看,這一次,我們在構造方法中,給”=”左邊的屬性前面都加上了this關鍵字,經過修改之後,重新運作main方法,就恢複了正常的運作效果。好,現在我們就來探究一下,加了this關鍵字之後,為什麼程式能夠”恢複正常”。剛才我們說過,”this”可以被解釋為” 本對象自己的...”,按照這個邏輯,”this.name”就可以被解釋為”本對象自己的name屬性”,是以在執行”this.name=name;”這條語句的時候,虛拟機就會把name參數的值”張三”指派給對象的name屬性。也就是說在這條指派語句中,”=”左邊的”this.name”表示對象的name屬性,而”=”右邊的name表示方法的name參數。

講到這裡,有的小夥伴可能會問:”this.name”為什麼不能被解釋為”本對象自己的name參數”呢?因為”參數”這個概念是就某個方法而言的,它相當于某個方法的”局部變量”,隻是這個”局部變量”比起在方法中定義的真正的局部變量來講有點特殊,它能夠接收從主調方法中傳遞過來的值。是以,當我們說到”參數”這個概念的時候,都是相對于一個”方法”而不是一個”對象”而言的,是以也就不會有”某個對象的參數”這一說法。是以,”this.name”隻能被虛拟機認定為本對象自己的name”屬性”,絕不會被當作name”參數”。

通過這個例子,希望大家能夠了解this關鍵字的意義。在程式中,所出現的”this.屬性名”是this關鍵字最常見的一種用法,也是我們給大家總結的this關鍵字的第一種用法。既然”this.屬性名”可以被解釋為”本對象自己的XX屬性”,那麼會不會有”this.方法名”這種用法呢?當然有這種用法,當程式中出現了”this.方法名”這種寫法,就可以被解釋為調用”本對象自己的XX方法”。來看下面的代碼:

java this關鍵字的使用_Java語言this關鍵字用法全面總結

這一次,我們給Person類增加了一個”打招呼”的方法叫做greet。在introduce方法當中,就可以通過”this.方法名”的方式來調用這個方法,表示調用的是”本對象自己的greet”方法。這是this關鍵字的第二種用法。當然,在introduce方法中并沒有出現其他對象,是以方法名前面的this關鍵字也可以省略不寫。

既然this關鍵字表示的是本對象自己,是以在代碼中可以直接用this來代表對象自身。比如說,在Ojbect類當中定義了一個equals()方法,這個方法用來比較自身對象與其他對象是不是相等,就直接可以用this來與其他對象做比較。

java this關鍵字的使用_Java語言this關鍵字用法全面總結

上面這段代碼就是Object類的equals()方法的源代碼,有興趣的小夥伴可以去看看。在代碼中直接用this關鍵字代表對象本身,并且和另一個對象obj做了比較。(關于==這個運算符到底比的什麼,大家可以看我的另一篇博文《你真的掌握了Java語言的"=="運算符嗎?我看未必!》)

其實,this關鍵字還有另外一種很重要的用法,那就是在this關鍵字的後面加上小括号,這樣就表示調用了某個類自身的構造方法,為了講解這種用法我們再來修改一下Person類。

java this關鍵字的使用_Java語言this關鍵字用法全面總結

這一次,我們給Person類又增加了一個構造方法。這個構造方法隻有2個參數,并且隻初始化2個屬性。為了講述友善,我們把上面的3個參數的構造方法稱之為”構造方法①”,把下面的2個參數的構造方法稱之為”構造方法②”。通過觀察不難發現,這兩個構造方法當中前2行代碼是互相重複的,為了避免這種重複性的代碼出現,我們可以在”構造方法①”當中調用”構造方法②”。調用的方式如下:

java this關鍵字的使用_Java語言this關鍵字用法全面總結

在”構造方法①”中,通過”this(參數);”的方式調用了”構造方法②”。這就是this關鍵字的又一種用法。很多小夥伴可能不了解,為什麼要通過這種方式來調用構造方法呢?我們難道不能直接寫一個”Person(name,age);”來調用嗎?這裡必須做出解釋:在Java語言中,一個類的構造方法與類名相同。但是,一個類當中也可以定義一個與類名相同的”普通方法”,換句話說就是:并不是隻有構造方法與類名相同,”普通方法”也可以取和類相同的名稱(隻不過全世界的程式員都不會這麼幹)。那麼,在這種情況下,編譯器如何區分這個方法是”普通方法”還是”構造方法”呢?很簡單,”普通方法”的名稱前面必須定義傳回值類型,而”構造方法”的名稱前面則沒有傳回值類型的定義。這樣,編譯器就能夠分得清哪個是”構造方法”,哪個是”和類同名的普通方法”。

定義的時候分得清,但是在調用的時候,都是通過方法名來調用的,這時如何分得清代碼中哪一句調用的是”構造方法”, 哪一句調用的是”和類同名的普通方法”呢?為了解決這個問題,Java語言規定,在本類中調用構造方法的時候,需要通過”this(參數)”的方式來調用。除此之外,Java語言還規定了這種調用方式所必須遵守的規則。首先,這種”this(參數)”的方式隻能在”其他構造方法中”使用,不能在普通方法中用。如果在普通方法中按這種方式使用,将被視為文法錯誤,如下圖所示

java this關鍵字的使用_Java語言this關鍵字用法全面總結

可以看到,在普通方法中按這樣的方式調用構造方法會出問題。

其次,在一個構造方法中,用”this(參數)”的形式調用構造方法,”this(參數)”必須寫在主調方法的第一行。第三,不能出現互相循環嵌套調用,也就是說,不能在構造方法①中調用構造方法②,又同時在構造方法②中調用構造方法①,如下圖所示

java this關鍵字的使用_Java語言this關鍵字用法全面總結

這種互相調用的寫法是絕對不允許的。

接下來我們再來思考兩個問題:首先,在main()方法中執行到”new Person("張三",20,178.5);”這句代碼時,實際上是調用了構造方法①,而構造方法①中又調用了構造方法②,兩個構造方法都被調用到了,那麼在記憶體中會不會建立兩個Person對象呢?答案是不會,為什麼呢?原因很簡單:構造方法①中調用了構造方法②,并沒有出現new關鍵字,調用構造方法②僅僅是完成了name和age這兩個屬性的初始化,并不會建立出兩個對象。

我們要思考的第二個問題是:既然Java語言允許”普通方法”的名稱與類名相同,而構造方法也與類名相同,那麼在Person以外的類當中如果寫上了”Person(參數)”這樣的代碼,虛拟機如何判斷所調用的是普通方法還是構造方法呢?答案也很簡單,如果”Person(參數)”的前面出現了new關鍵字,這就說明調用的是構造方法,否則說明調用的是普通方法。

講到這裡,我們就把this關鍵字最常用的幾種用法講完了,其實,this關鍵字在我們編寫内部類代碼的時候,還有一種用途,那就是區分屬性或方法的具體歸屬。我們來看下面的代碼:

java this關鍵字的使用_Java語言this關鍵字用法全面總結

在這段代碼中,定義了外部類Outter,Outter有一個屬性a,并且Outter中又定義了内部類,在内部類的printA()方法中調用了外部類的a屬性。我們都知道,一個内部類可以直接通路它所在外部類的屬性和方法。這個特性在我們的上面這段代碼中得到了展現。但是,如果内部類中出現了與外部類同名的屬性或方法時,該如何區分調用的到底是哪個屬性或方法呢?比如說,在Inner類中也出現了a屬性,那麼輸出語句中的a到底是指哪個a呢?很簡單,如果輸出語句中直接寫a,那麼調用的是内部類的a屬性。為了強調它是内部類的a屬性,我們也可以在a的前面加this關鍵字。如果我們希望調用的是外部類的a屬性,可以用”外部類名.this.a”的方式來調用,如下圖所示:

java this關鍵字的使用_Java語言this關鍵字用法全面總結

以上我們就把this關鍵字的意義和它的各種用法講完了,簡單總結一下:

1、this:表示自身對象,也就是本對象自己

2、this.屬性名:表示本對象自己的屬性

3、this.方法名:表示本對象自己的方法

4、this(參數)表示本對象自身的構造方法(注:”構造方法”這個概念是相對于”類”而言的,但具體到this(參數)這種用法時,表示”我這個對象自己的構造方法”)

5、外部類名.this.屬性:表示在内部類中調用的是外部類的某個屬性(調用外部類方法亦同)

希望本文能夠幫助初學者深入了解this關鍵字的作用。

歡迎各位小夥伴關注我的專欄,專欄将持續輸出有益有趣的技術文章。如想系統學習Java程式設計,可以點選下面的連結觀看我的視訊課程,有問題也可以加入我的QQ群291839907一起讨論。

沙利穆_騰訊課堂​shalimu.ke.qq.com

java this關鍵字的使用_Java語言this關鍵字用法全面總結