關於super和this有一個奇怪的現象: 例1: class grandfather{ String name="grandfather"; } class father extends grandfather{ String name="father"; void show(){ System. ...
關於super和this有一個奇怪的現象: 例1:
class grandfather{ String name="grandfather"; } class father extends grandfather{ String name="father"; void show(){ System.out.println("father.show-->"+this.name+"--"+super.name); } } class son extends father{ void rs(){ super.show(); this.show(); } } public class super_this2 { public static void main(String[] args) { son s=new son(); s.rs(); } }運行結果: father.show-->father--grandfather father.show-->father--grandfather 使用super.show()和使用this.show()輸出的結果是一樣的。存在這種現象的還有這種現象還有super.getClass()和this.getClass()等。
例2:
public class super_this2{ public static void main(String[] args) { new super_this2().test(); } public void test(){ System.out.println(super.getClass()); System.out.println(this.getClass()); } }運行結果:
class super_this2 class super_this2 現在我們分析這個現象。 1.在例1的子類中覆蓋show() 例3:
class grandfather{ String name="grandfather"; } class father extends grandfather{ String name="father"; void show(){ System.out.println("father.show-->"+this.name+"--"+super.name); } } class son extends father{ void show(){ System.out.println("son.show-->"+this.name+"--"+super.name); } void rs(){ super.show(); this.show(); } } public class super_this2{ public static void main(String[] args) { son s=new son(); s.rs(); } }運行結果:
father.show-->father--grandfather son.show-->father--father 這說明 A.super.方法/變數調用的確實是父類的方法/變數;this.方法/變數調用的確實是當前對象的方法/變數 2.而如果子類沒有覆蓋show()時,子類輸出結果和父類一樣,比如例1,再比如下麵的例子: 例4:
public class Test2 { public static void main(String[] args) { ch c=new ch(); c.m6(); c.m7(); c.m8(); } static class fa{ final void m6(){ System.out.println("father's m6"); } static void m7(){ System.out.println("father's m7"); } void m8(){ System.out.println("father's m8"); } } static class ch extends fa{ void m8(){ System.out.println("child's m8"); } } }運行結果: father's m6 father's m7 child's m8 這裡,m6,m7,m8都被繼承了,然後m6,m7沒有被覆蓋,輸出的是父類的結果。m8被重寫輸出子類的結果。
這說明: B.如果子類沒有重寫或隱藏父類的某個方法和變數,那麼子類調用繼承的方法或變數來自父類。
所以A和B綜合的結果是:AB.super.方法/變數調用的確實是父類的方法/變數;this.方法/變數調用的確實是當前對象的方法/變數,但如果this所在對象沒有重寫或隱藏父類的方法或變數,那麼它調用的繼承來的方法或變數來自父類 3.如果在例1的son類中添加 String name="son"; 例5:
class grandfather{ String name="grandfather"; } class father extends grandfather{ String name="father"; void show(){ System.out.println("father.show-->"+this.name+"--"+super.name); } } class son extends father{ String name="son";//隱藏father類的name屬性 void rs(){ super.show(); this.show(); } } public class super_this2{ public static void main(String[] args) { son s=new son(); s.rs(); } }運行結果和例1一樣: father.show-->father--grandfather father.show-->father--grandfather
但如果像下麵這樣不隱藏而直接修改name屬性: 例6:
class grandfather{ String name="grandfather"; } class father extends grandfather{ String name="father";// void show(){ System.out.println("father.show-->"+this.name+"--"+super.name); } } class son extends father{ // String name="son"; // 去掉 public son(){ name="son";//不隱藏父類的name , 在構造方法中直接修改 } void rs(){ super.show(); this.show(); } } public class super_this2{ public static void main(String[] args) { son s=new son(); s.rs(); } }運行結果:
father.show-->son--grandfather father.show-->son--grandfather
這說明: C.隱藏變數不會對父類變數產生影響,但是對繼承來的變數進行修改會對父類的變數產生直接影響。
現在你把例6的father類中的 String name="father"去掉試試:
class grandfather{ String name="grandfather"; } class father extends grandfather{ // String name="father";// 去掉 void show(){ System.out.println("father.show-->"+this.name+"--"+super.name); } } class son extends father{ // String name="son"; // 去掉 public son(){ name="son"; } void rs(){ super.show(); this.show(); } } public class super_this2{ public static void main(String[] args) { son s=new son(); s.rs(); } }運行結果: father.show-->son--son father.show-->son--son 原因正如C所說的,String name="father"隱藏了爺爺類的String name="grandfather",所以後面修改name="son"不會對爺爺類產生影響,現在去掉隱藏後,對繼承的name屬性的修改就會影響爺爺類的name屬性。 4.提2個問題:(1)方法體裡面的this和super與調用它們對象是什麼關係,(2)this和super與方法體裡面的this和super是什麼關係? 即這裡son對象調用了super和this,super和this調用了super和this,那麼對象s與super和this是什麼關係?super和super,this是什麼關係?this和super,this是什麼關係?
class grandfather{ String name="grandfather"; public String toString(){ return "grandfather toString"; } public static String toString2(){ return "grandfather static toString"; } } class father extends grandfather{ String name="father"; void show(){ System.out.println("father.show-->"+this.name+"--"+super.name); System.out.println("father.show-->"+this.toString()+"--"+super.toString()); System.out.println("father.show-->"+this.toString2()+"--"+super.toString2()); } public String toString(){ return "father toString"; } public static String toString2(){ return "father static toString"; } } class son extends father{ String name="son"; void rs(){ super.show(); System.out.println("==========================="); this.show(); } public String toString(){ return "son toString"; } public static String toString2(){ return "son static toString"; } } public class super_this2{ public static void main(String[] args) { son s=new son(); s.rs(); } }
運行結果 father.show-->father--grandfather father.show-->son toString--grandfather toString father.show-->father static toString--grandfather static toString =========================== father.show-->father--grandfather father.show-->son toString--grandfather toString father.show-->father static toString--grandfather static toString |
.隱藏變數不會對父類變數產生影響,但是對繼承來的變數進行修改會對父類的變數產生直接影響。
最後看一道題:
class father{ void show(){ System.out.println("father getClass-->"+this.getClass()+"--"+super.getClass()); System.out.println("father getSuperclass-->"+this.getClass().getSuperclass()+"--"+super.getClass().getSuperclass()); } } class son extends father{ void rs(){ super.show(); System.out.println("==========================="); this.show(); } } public class super_this3{ public static void main(String[] args) { son s=new son(); s.rs(); } }father getClass-->class son--class son father getSuperclass-->class father--class father =========================== father getClass-->class son--class son father getSuperclass-->class father--class father 主要是因為super.getClass()返回的是son.class,然後son.class.getName()輸出son。 getClass是final方法,this.getClass肯定來自父類。getClass的源碼:
Java_java_lang_Object_getClass(JNIEnv *env, jobject this) { if (this == NULL) { JNU_ThrowNullPointerException(env, NULL); return 0; } else { return (*env)->GetObjectClass(env, this); } }this指正在運行的對象。所以getClass返回son.class 文章原創,謝絕轉載,歡迎指正。