【java】this()与super()使用详解
原文地址:http://www.cnblogs.com/hasse/p/5023392.html
this三大作用:
this調用屬性、調用方法、利用this表示當前對象。
this
this是自身的一個對象,代表對象本身,可以理解為:指向對象本身的一個指針。
this的用法在java中大體可以分為3種:
1.普通的直接引用
這種就不用講了,this相當于是指向當前對象本身。
2.形參與成員名字重名,用this來區分:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class?Person { ????private?int?age =?10; ????public?Person(){ ????System.out.println("初始化年齡:"+age); } ????public?int?GetAge(int?age){ ????????this.age = age; ????????return?this.age; ????} } public?class?test1 { ????public?static?void?main(String[] args) { ????????Person Harry =?new?Person(); ????????System.out.println("Harry's age is "+Harry.GetAge(12)); ????} }??????? |
運行結果:
初始化年齡:10
Harry's age is 12
可以看到,這里age是GetAge成員方法的形參,this.age是Person類的成員變量。
3.引用構造函數
這個和super放在一起講,見下面。
super
super可以理解為是指向自己超(父)類對象的一個指針,而這個超類指的是離自己最近的一個父類。
super也有三種用法:
1.普通的直接引用
與this類似,super相當于是指向當前對象的父類,這樣就可以用super.xxx來引用父類的成員。
2.子類中的成員變量或方法與父類中的成員變量或方法同名
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class?Country { ????String name; ????void?value() { ???????name =?"China"; ????} } ?? class?City?extends?Country { ????String name; ????void?value() { ????name =?"Shanghai"; ????super.value();??????//調用父類的方法 ????System.out.println(name); ????System.out.println(super.name); ????} ?? ????public?static?void?main(String[] args) { ???????City c=new?City(); ???????c.value(); ???????} } |
運行結果:
Shanghai
China
可以看到,這里既調用了父類的方法,也調用了父類的變量。若不調用父類方法value(),只調用父類變量name的話,則父類name值為默認值null。
3.引用構造函數
super(參數):調用父類中的某一個構造函數(應該為構造函數中的第一條語句)。 this(參數):調用本類中另一種形式的構造函數(應該為構造函數中的第一條語句)。| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | class?Person {? ????public?static?void?prt(String s) {? ???????System.out.println(s);? ????}? ??? ????Person() {? ???????prt("父類·無參數構造方法: "+"A Person.");? ????}//構造方法(1)? ???? ????Person(String name) {? ???????prt("父類·含一個參數的構造方法: "+"A person's name is "?+ name);? ????}//構造方法(2)? }? ???? public?class?Chinese?extends?Person {? ????Chinese() {? ???????super();?// 調用父類構造方法(1)? ???????prt("子類·調用父類”無參數構造方法“: "+"A chinese coder.");? ????}? ???? ????Chinese(String name) {? ???????super(name);// 調用父類具有相同形參的構造方法(2)? ???????prt("子類·調用父類”含一個參數的構造方法“: "+"his name is "?+ name);? ????}? ???? ????Chinese(String name,?int?age) {? ???????this(name);// 調用具有相同形參的構造方法(3)? ???????prt("子類:調用子類具有相同形參的構造方法:his age is "?+ age);? ????}? ???? ????public?static?void?main(String[] args) {? ???????Chinese cn =?new?Chinese();? ???????cn =?new?Chinese("codersai");? ???????cn =?new?Chinese("codersai",?18);? ????}? } |
運行結果:
父類·無參數構造方法: A Person.
子類·調用父類”無參數構造方法“: A chinese coder.
父類·含一個參數的構造方法: A person's name is codersai
子類·調用父類”含一個參數的構造方法“: his name is codersai
父類·含一個參數的構造方法: A person's name is codersai
子類·調用父類”含一個參數的構造方法“: his name is codersai
子類:調用子類具有相同形參的構造方法:his age is 18
從本例可以看到,可以用super和this分別調用父類的構造方法和本類中其他形式的構造方法。
例子中Chinese類第三種構造方法調用的是本類中第二種構造方法,而第二種構造方法是調用父類的,因此也要先調用父類的構造方法,再調用本類中第二種,最后是重寫第三種構造方法。
?
super和this的異同:
- super(參數):調用基類中的某一個構造函數(應該為構造函數中的第一條語句)?
- this(參數):調用本類中另一種形成的構造函數(應該為構造函數中的第一條語句)
- super: 它引用當前對象的直接父類中的成員(用來訪問直接父類中被隱藏的父類中成員數據或函數,基類與派生類中有相同成員定義時如:super.變量名????super.成員函數據名(實參)
- this:它代表當前對象名(在程序中易產生二義性之處,應使用this來指明當前對象;如果函數的形參與類中的成員數據同名,這時需用this來指明成員變量名)
- 調用super()必須寫在子類構造方法的第一行,否則編譯不通過。每個子類構造方法的第一條語句,都是隱含地調用super(),如果父類沒有這種形式的構造函數,那么在編譯的時候就會報錯。
- super()和this()類似,區別是,super()從子類中調用父類的構造方法,this()在同一類內調用其它方法。
- super()和this()均需放在構造方法內第一行。
- 盡管可以用this調用一個構造器,但卻不能調用兩個。
- this和super不能同時出現在一個構造函數里面,因為this必然會調用其它的構造函數,其它的構造函數必然也會有super語句的存在,所以在同一個構造函數里面有相同的語句,就失去了語句的意義,編譯器也不會通過。
- this()和super()都指的是對象,所以,均不可以在static環境中使用。包括:static變量,static方法,static語句塊。
- 從本質上講,this是一個指向本對象的指針,?然而super是一個Java關鍵字。
1.this關鍵字
對于上述需要注意的地方: 1.不是重載即在構造器中調用構造器可以直接調用其方法,無需this。在需要明確的地方使用即可
2.疑惑點
this關鍵字對于將當前對象傳遞給其他的方法也很有用,這一點自己現在也不是很熟練
2.在構造器中調用構造器
例子:
package test;public class Test {private int i=0;//第一個構造器:有一個int型形參Test(int i){System.out.println("i:"+this.i);this.i=i+1;//此時this表示引用成員變量i,而非函數參數i//下面的i表示形參i,this.i表示數據成員System.out.println("Int constructor i——this.i: "+i+" —— "+this.i);System.out.println("i:"+this.i);System.out.println(" i-1: "+(i-1)+" this.i+1: "+(this.i+1));//從兩個輸出結果充分證明了i和this.i是不一樣的!}// 第二個構造器:有一個String型形參Test(String s){// 重新調用新的構造器之后,數據成員的值不再受到上一個的影響 // 難道是因為每個構造器都有自己獨立內存空間嗎?System.out.println("2i:"+this.i);System.out.println("String constructor: "+s);}// 第三個構造器:有一個int型形參和一個String型形參Test(int i,String s){this(s);//this調用第二個構造器/*this(i);*//*此處不能用,因為其他任何方法都不能調用構造器,只有構造方法能調用他。但是必須注意:就算是構造方法調用構造器,也必須為于其第一行,構造方法也只能調用一個且僅一次構造器!http://blog.sina.com.cn/s/blog_8612e75d0100ze1m.html*/System.out.println("3i:"+this.i);this.i=i++;//this以引用該類的成員變量System.out.println("Int constructor: "+i+"\n"+"String constructor: "+s);}/* Test(int i ,String s,double a){this(i);System.out.println("5i:"+this.i);}*/public Test increment(){System.out.println("4i:"+this.i);this.i++;return this;//返回的是當前的對象,該對象屬于(Test)}public static void main(String[] args){Test tt0=new Test(10);Test tt1=new Test("ok");Test tt2=new Test(20,"ok again!");/* Test tt3=new Test(15, "okhushid", 0.12345);*///由于increment()通過this關鍵字返回了當前對象的引用,所以很容易在一條語句里面對同一個對象執行多次操作System.out.println(tt0.increment().increment().increment().i); // 輸出的是this.i,就相當于輸出其數據成員System.out.println(tt0.increment().increment().increment()); // 輸出的是test.Test@2b0a141e,這是什么?這是java中的內存地址嗎?//http://www.cnblogs.com/java-class/archive/2012/12/19/2825463.html}}
關于this()與super()共用的問題:
package test;class TestA {public TestA() {System.out.println("A");}}class TestB extends TestA {public TestB(int i) {super(); // this();}public TestB() {this(3);System.out.println("B");}}public class Test {public static void main(String[] ars) {new TestB(1);new TestB();}}super()和this ()不能共存,否則編譯時會報異常。
Constructor call must be the first statement in a constructor
換句話說就是super()和this ()都必須在構造方法的第一行。
this(有參數/無參數) 用于調用本類相應的構造函數
super(有參數/無參數) 用于調用父類相應的構造函數
而且在構造函數中,調用必須寫在構造函數定義的第一行,不能在構造函數的后面使用。
一個構造函數定義中不能同時包括this調用和super調用,如果想同時包括的話,可以在一每構造器中使用一個。
?補充:
? ?用類名定義一個變量的時候,定義的應該只是一個引用,外面可以通過這個引用來訪問這個類里面的屬性和方法,那們類里面是夠也應該有一個引用來訪問自己的屬性和方法納?JAVA提供了一個很好的東西,就是 this 對象,它可以在類里面來引用這個類的屬性和方法。
public class ThisDemo { String name="Mick";public void print(String name){System.out.println("類中的屬性 name="+this.name);System.out.println("局部傳參的屬性="+name);} public static void main(String[] args) {ThisDemo tt=new ThisDemo();tt.print("Orson");} }
自我問題:
http://bbs.csdn.net/topics/391819324?page=1#post-400326846
第一個問題:每次重新調用一個新的構造器之后,this.i的數據都會恢復到原來了0;上一個構造器的this.i的結果沒有保存,難道在java中每個構造器都有自己的內存空間地址嗎?
第二個問題:???System.out.println(tt0.increment().increment().increment());
//???????輸出的是test.Test@2b0a141e,這是什么?這是java中的內存地址嗎?
第一個問題:
構造器(構造函數,Constructor)是一種特殊的函數,它是用來初始化一個“剛剛建立”的對象的方法。不同的構造器重載用于以不同的方式初始化這個對象(其中的邏輯是由編程人員自由控制的)。對于同一個類內的構造器,對于每個對象只能被調用一次,且是由new方法發起調用,可以使用super(調用父類的構造方法)和this(調用本類的構造方法)在不同構造器方法之間跳轉,但是每個構造方法最多被調用一遍,同一個類內的構造方法最多有一個是實質上執行的(如果遞歸,編譯器會報錯)。this是對當前對象的引用,每次構造器調用時都是作用于一個全新的對象,故每次調用時其類中數據成員的值(那個i是成員變量,在每個對象中有獨立的存儲空間)一定是未初始化的默認值。
static:只有靜態成員變量才是整個類共用的。對于非靜態成員變量每個對象保存一個獨立的值(當然占用的就是對象的空間)。
第二個問題:
當沒有重寫toString方法時,默認會使用Object類提供的toString方法,其規則是:類全名@類對象的hashcode方法返回值。當沒有重寫hashCode方法時,默認使用Object類的hashCode方法,它是java對一個對象的標識號,可能由不同機制生成,不一定是內存地址,但是可能與之相關(通常實現采用的是將地址轉換為int值的方法)。
要搞清楚成員變量和局部變量
Test(int?i){?},這個構造器中形參?i?是一個局部變量,作用域是這個構造器的大括號,意思是?聲明一個局部變量i,是這個構造器的形參,其值為傳入的實參的值,在這個構造器中的i?是指的這個局部變量。
在類中也聲明了一個成員變量i,在構造器中也能調用這個變量,但是名字都一樣,為了區分應this.i表示這個成員變量,這里的this是指本類的屬性
總結
以上是生活随笔為你收集整理的【java】this()与super()使用详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Leaflet地图初始化地图(谷歌+天地
- 下一篇: Linux下3种常用的网络测速工具