新聞中心
“哥,被喊大舅子的感覺怎么樣啊?”三妹不懷好意地對我說,她眼睛里充滿著不屑。

成都創(chuàng)新互聯(lián)成都網(wǎng)站建設按需定制,是成都營銷推廣公司,為成都門簾提供網(wǎng)站建設服務,有成熟的網(wǎng)站定制合作流程,提供網(wǎng)站定制設計服務:原型圖制作、網(wǎng)站創(chuàng)意設計、前端HTML5制作、后臺程序開發(fā)等。成都網(wǎng)站制作熱線:18982081108
“說實話,這種感覺還不錯。”我有點難為情的回答她,“不過,有一點令我感到些許失落。大家的焦點似乎都是你的顏值,完全忽略了我的盛世美顏啊!”
“哥,你想啥呢,那是因為你文章寫得好,不然誰認識我是誰啊!有你這樣的哥哥,我還是挺自豪的?!比绵嵵仄涫碌卣f,“話說今天咱學啥呢?”
“三妹啊,你這句話說得我喜歡。今天來學習一下 Java 中的 this 關鍵字吧?!焙攘艘豢谵r(nóng)夫山泉后,我對三妹說。
“this 關鍵字有很多種用法,其中最常用的一個是,它可以作為引用變量,指向當前對象?!蔽颐鎺е鴺銓崯o華的微笑繼續(xù)說,“除此之外, this 關鍵字還可以完成以下工作?!?/p>
- 調(diào)用當前類的方法;
- this() 可以調(diào)用當前類的構造方法;
- this 可以作為參數(shù)在方法中傳遞;
- this 可以作為參數(shù)在構造方法中傳遞;
- this 可以作為方法的返回值,返回當前類的對象。
01、 指向當前對象
“三妹,來看下面這段代碼。”話音剛落,我就在鍵盤上噼里啪啦一陣敲。
- public class WithoutThisStudent {
- String name;
- int age;
- WithoutThisStudent(String name, int age) {
- name = name;
- age = age;
- }
- void out() {
- System.out.println(name+" " + age);
- }
- public static void main(String[] args) {
- WithoutThisStudent s1 = new WithoutThisStudent("沉默王二", 18);
- WithoutThisStudent s2 = new WithoutThisStudent("沉默王三", 16);
- s1.out();
- s2.out();
- }
- }
“在上面的例子中,構造方法的參數(shù)名和實例變量名相同,由于沒有使用 this 關鍵字,所以無法為實例變量賦值?!蔽姨鹩沂值氖持?,指著屏幕上的 name 和 age 對著三妹說。
“來看一下程序的輸出結果?!?/p>
- null 0
- null 0
“從結果中可以看得出來,盡管創(chuàng)建對象的時候傳遞了參數(shù),但實例變量并沒有賦值。這是因為如果構造方法中沒有使用 this 關鍵字的話,name 和 age 指向的并不是實例變量而是參數(shù)本身?!蔽野巡弊优は蛴覀?,看著三妹說。
“那怎么解決這個問題呢?哥?!比弥钡貑?。
“如果參數(shù)名和實例變量名產(chǎn)生了沖突.....”我正準備給出答案,三妹打斷了我。
“難道用 this 嗎?”三妹脫口而出。
“哇,越來越棒了呀,你。”我感覺三妹在學習 Java 這條道路上逐漸有了自己主動思考的意愿。
“是的,來看加上 this 關鍵字后的代碼?!?/p>
安靜的屋子里又響起了一陣噼里啪啦的鍵盤聲。
- public class WithThisStudent {
- String name;
- int age;
- WithThisStudent(String name, int age) {
- this.name = name;
- this.age = age;
- }
- void out() {
- System.out.println(name+" " + age);
- }
- public static void main(String[] args) {
- WithThisStudent s1 = new WithThisStudent("沉默王二", 18);
- WithThisStudent s2 = new WithThisStudent("沉默王三", 16);
- s1.out();
- s2.out();
- }
- }
“再來看一下程序的輸出結果?!?/p>
- 沉默王二 18
- 沉默王三 16
“這次,實例變量有值了,在構造方法中,this.xxx 指向的就是實例變量,而不再是參數(shù)本身了。”我慢吞吞地說著,“當然了,如果參數(shù)名和實例變量名不同的話,就不必使用 this 關鍵字,但我建議使用 this 關鍵字,這樣的代碼更有意義?!?/p>
03、調(diào)用當前類的方法
“仔細聽,三妹,看我敲鍵盤的速度是不是夠快。”
- public class InvokeCurrentClassMethod {
- void method1() {}
- void method2() {
- method1();
- }
- public static void main(String[] args) {
- new InvokeCurrentClassMethod().method1();
- }
- }
“仔細瞧,三妹,上面這段代碼中沒有見到 this 關鍵字吧?”我面帶著神秘的微笑,準備給三妹變個魔術。
“確實沒有,哥,我確認過了?!?/p>
“那接下來,神奇的事情就要發(fā)生了。”我突然感覺劉謙附身了。
我快速的在 classes 目錄下找到 InvokeCurrentClassMethod.class 文件,然后雙擊打開(IDEA 默認會使用 FernFlower 打開字節(jié)碼文件)。
- public class InvokeCurrentClassMethod {
- public InvokeCurrentClassMethod() {
- }
- void method1() {
- }
- void method2() {
- this.method1();
- }
- public static void main(String[] args) {
- (new InvokeCurrentClassMethod()).method1();
- }
- }
“瞪大眼睛仔細瞧,三妹,this 關鍵字是不是出現(xiàn)了?”
“哇,真的呢,好神奇啊!”三妹為了配合我的演出,也是十二分的賣力。
“我們可以在一個類中使用 this 關鍵字來調(diào)用另外一個方法,如果沒有使用的話,編譯器會自動幫我們加上?!蔽覍ψ约荷詈竦木幊坦Φ壮錆M自信,“在源代碼中,method2() 在調(diào)用 method1() 的時候并沒有使用 this 關鍵字,但通過反編譯后的字節(jié)碼可以看得到?!?/p>
04、調(diào)用當前類的構造方法
“再來看下面這段代碼。”
- public class InvokeConstrutor {
- InvokeConstrutor() {
- System.out.println("hello");
- }
- InvokeConstrutor(int count) {
- this();
- System.out.println(count);
- }
- public static void main(String[] args) {
- InvokeConstrutor invokeConstrutor = new InvokeConstrutor(10);
- }
- }
“在有參構造方法 InvokeConstrutor(int count) 中,使用了 this() 來調(diào)用無參構造方法 InvokeConstrutor()。”這次,我換成了左手的食指,指著屏幕對三妹說,“this() 可用于調(diào)用當前類的構造方法——構造方法可以重用了?!?/p>
“來看一下輸出結果。”
- hello
- 10
“真的啊,無參構造方法也被調(diào)用了,所以程序輸出了 hello。”三妹看到輸出結果后不假思索地說。
“也可以在無參構造方法中使用 this() 并傳遞參數(shù)來調(diào)用有參構造方法。”話音沒落,我就在鍵盤上敲了起來,“來看下面這段代碼。”
- public class InvokeParamConstrutor {
- InvokeParamConstrutor() {
- this(10);
- System.out.println("hello");
- }
- InvokeParamConstrutor(int count) {
- System.out.println(count);
- }
- public static void main(String[] args) {
- InvokeParamConstrutor invokeConstrutor = new InvokeParamConstrutor();
- }
- }
“再來看一下程序的輸出結果。”
- 10
- hello
“不過,需要注意的是,this() 必須放在構造方法的第一行,否則就報錯了?!?/p>
05、作為參數(shù)在方法中傳遞
“來看下面這段代碼?!?/p>
- public class ThisAsParam {
- void method1(ThisAsParam p) {
- System.out.println(p);
- }
- void method2() {
- method1(this);
- }
- public static void main(String[] args) {
- ThisAsParam thisAsParam = new ThisAsParam();
- System.out.println(thisAsParam);
- thisAsParam.method2();
- }
- }
“this 關鍵字可以作為參數(shù)在方法中傳遞,此時,它指向的是當前類的對象?!币徊恍⌒模雮€小時過去了,我感到嗓子冒煙,于是趕緊又喝了一口水,潤潤嗓子后繼續(xù)說道。
“來看一下輸出結果,你就明白了,三妹?!?/p>
- com.itwanger.twentyseven.ThisAsParam@77459877
- com.itwanger.twentyseven.ThisAsParam@77459877
“method2() 調(diào)用了 method1(),并傳遞了參數(shù) this,method1() 中打印了當前對象的字符串。main() 方法中打印了 thisAsParam 對象的字符串。從輸出結果中可以看得出來,兩者是同一個對象?!?/p>
06、作為參數(shù)在構造方法中傳遞
“繼續(xù)來看代碼。”
- public class ThisAsConstrutorParam {
- int count = 10;
- ThisAsConstrutorParam() {
- Data data = new Data(this);
- data.out();
- }
- public static void main(String[] args) {
- new ThisAsConstrutorParam();
- }
- }
- class Data {
- ThisAsConstrutorParam param;
- Data(ThisAsConstrutorParam param) {
- this.param = param;
- }
- void out() {
- System.out.println(param.count);
- }
- }
“在構造方法 ThisAsConstrutorParam() 中,我們使用 this 關鍵字作為參數(shù)傳遞給了 Data 對象,它其實指向的就是 new ThisAsConstrutorParam() 這個對象?!?/p>
“this 關鍵字也可以作為參數(shù)在構造方法中傳遞,它指向的是當前類的對象。當我們需要在多個類中使用一個對象的時候,這非常有用?!?/p>
“來看一下輸出結果?!?/p>
- 10
07、作為方法的返回值
“需要休息會嗎?三妹”
“沒事的,哥,我的注意力還是很集中的,你繼續(xù)講吧。”
“好的,那來繼續(xù)看代碼?!?/p>
- public class ThisAsMethodResult {
- ThisAsMethodResult getThisAsMethodResult() {
- return this;
- }
- void out() {
- System.out.println("hello");
- }
- public static void main(String[] args) {
- new ThisAsMethodResult().getThisAsMethodResult().out();
- }
- }
“getThisAsMethodResult() 方法返回了 this 關鍵字,指向的就是 new ThisAsMethodResult() 這個對象,所以可以緊接著調(diào)用 out() 方法——達到了鏈式調(diào)用的目的,這也是 this 關鍵字非常經(jīng)典的一種用法。”
“鏈式調(diào)用的形式在 JavaScript 代碼更加常見。”為了向三妹證實這一點,我打開了 jQuery 的源碼。
“原來這么多鏈式調(diào)用啊!”三妹感嘆到。
“是的。”我點點頭,然后指著 getThisAsMethodResult() 方法的返回值對三妹說,“需要注意的是,this 關鍵字作為方法的返回值的時候,方法的返回類型為類的類型?!?/p>
“來看一下輸出結果?!?/p>
- hello
“那么,關于 this 關鍵字的介紹,就到此為止了?!蔽一顒恿艘幌陆┯驳牟弊雍螅瑢θ谜f,“如果你學習勁頭還可以的話,我們順帶把 super 關鍵字捎帶著過一下,怎么樣?”
“不用了吧,聽說 super 關鍵字更簡單,我自己看看就行了,不用你講了!”
“不不不,三妹啊,你得假裝聽一下,不然我怎么向讀者們交差。”
“噢噢噢噢?!比靡馕渡铋L地笑了。
08、super 關鍵字
“super 關鍵字的用法主要有三種?!?/p>
- 指向父類對象;
- 調(diào)用父類的方法;
- super() 可以調(diào)用父類的構造方法。
“其實和 this 有些相似,只不過用意不大相同?!蔽叶似鹚?,咕咚咕咚又喝了幾大口,好渴?!懊慨攧?chuàng)建一個子類對象的時候,也會隱式的創(chuàng)建父類對象,由 super 關鍵字引用?!?/p>
“如果父類和子類擁有同樣名稱的字段,super 關鍵字可以用來訪問父類的同名字段?!?/p>
“來看下面這段代碼。”
- public class ReferParentField {
- public static void main(String[] args) {
- new Dog().printColor();
- }
- }
- class Animal {
- String color = "白色";
- }
- class Dog extends Animal {
- String color = "黑色";
- void printColor() {
- System.out.println(color);
- System.out.println(super.color);
- }
- }
“父類 Animal 中有一個名為 color 的字段,子類 Dog 中也有一個名為 color 的字段,子類的 printColor() 方法中,通過 super 關鍵字可以訪問父類的 color。”
“來看一下輸出結果?!?/p>
- 黑色
- 白色
“當子類和父類的方法名相同時,可以使用 super 關鍵字來調(diào)用父類的方法。換句話說,super 關鍵字可以用于方法重寫時訪問到父類的方法?!?/p>
- public class ReferParentMethod {
- public static void main(String[] args) {
- new Dog().work();
- }
- }
- class Animal {
- void eat() {
- System.out.println("吃...");
- }
- }
- class Dog extends Animal {
- @Override
- void eat() {
- System.out.println("吃...");
- }
- void bark() {
- System.out.println("汪汪汪...");
- }
- void work() {
- super.eat();
- bark();
- }
- }
“瞧,三妹。父類 Animal 和子類 Dog 中都有一個名為 eat() 的方法,通過 super.eat() 可以訪問到父類的 eat() 方法?!?/p>
等三妹在自我消化的時候,我在鍵盤上又敲完了一串代碼。
- public class ReferParentConstructor {
- public static void main(String[] args) {
- new Dog();
- }
- }
- class Animal {
- Animal(){
- System.out.println("動物來了");
- }
- }
- class Dog extends Animal {
- Dog() {
- super();
- System.out.println("狗狗來了");
- }
- }
“子類 Dog 的構造方法中,第一行代碼為 super(),它就是用來調(diào)用父類的構造方法的?!?/p>
“來看一下輸出結果?!?/p>
- 動物來了
- 狗狗來了
“當然了,在默認情況下,super() 是可以省略的,編譯器會主動去調(diào)用父類的構造方法。也就是說,子類即使不使用 super() 主動調(diào)用父類的構造方法,父類的構造方法仍然會先執(zhí)行?!?/p>
- public class ReferParentConstructor {
- public static void main(String[] args) {
- new Dog();
- }
- }
- class Animal {
- Animal(){
- System.out.println("動物來了");
- }
- }
- class Dog extends Animal {
- Dog() {
- System.out.println("狗狗來了");
- }
- }
“輸出結果和之前一樣?!?/p>
- 動物來了
- 狗狗來了
“super() 也可以用來調(diào)用父類的有參構造方法,這樣可以提高代碼的可重用性。”
- class Person {
- int id;
- String name;
- Person(int id, String name) {
- this.id = id;
- this.name = name;
- }
- }
- class Emp extends Person {
- float salary;
- Emp(int id, String name, float salary) {
- super(id, name);
- this.salary = salary;
- }
- void display() {
- System.out.println(id + " " + name + " " + salary);
- }
- }
- public class CallParentParamConstrutor {
- public static void main(String[] args) {
- new Emp(1, "沉默王二", 20000f).display();
- }
- }
“Emp 類繼承了 Person 類,也就繼承了 id 和 name 字段,當在 Emp 中新增了 salary 字段后,構造方法中就可以使用 super(id, name) 來調(diào)用父類的有參構造方法。”
“來看一下輸出結果?!?/p>
- 1 沉默王二 20000.0
三妹點了點頭,所有所思。
09、ending
“三妹,this 和 super 關鍵字我們就學到這里吧,你還有什么問題嗎?”三妹學習 Java 的勁頭讓我對她未來的編程生涯充滿了信心。
“沒有了,哥,你講的挺棒的,我已經(jīng)全部都消化了?!比玫哪樕蠋е⑿Γ皩α?,哥,《教妹學 Java》已經(jīng)更新到第 20 講了,你的 PDF 別忘記同步更新啊!”
“一定一定。”
聽我說完,三妹放心地回她自己的小屋休息去了。我趁她不在的這一會時間,把這篇文章編輯到了“沉默王二”公眾號,滿懷期許地等待留言區(qū)的新一波“大舅哥”。
本文轉載自微信公眾號「沉默王二」,可以通過以下二維碼關注。轉載本文請聯(lián)系沉默王二公眾號。
當前標題:我妹說,只用講This,不用講Super
當前網(wǎng)址:http://www.5511xx.com/article/ccisgeo.html


咨詢
建站咨詢
