先放一段代碼,通過修改參數來了解以下四個問題:
1.父類子類混合建立一個新對象的構造邏輯(多态性及動态綁定)
2.this.方法實質
3.靜态方法的隐藏(成員變量)
4.非靜态方法的覆寫
對1的解釋:聲明父類建立子類對象的與正常建立對象的差別(A p = new B()):
先看如下代碼,A是B的父類,m()被覆寫。
class A {
int x=;//被隐藏
A() {
System.out.println("這裡建構了一個父類對象");
}
void m() {//被覆寫
System.out.println("這裡是父類的執行個體方法m()");
}
void m1() {
this.m();
this.m2();
this.m3();
System.out.println(this.x);
System.out.println("這裡是父類的執行個體方法m1()");
}
static void m2(){//被隐藏
System.out.println("這裡是父類的靜态方法m2()");
}
void m3() {//未被覆寫
System.out.println("這裡是父類的執行個體方法m3()");
}
}
class B extends A {
int x=;
B() {
System.out.println("這裡建構了一個子類對象");
}
void m() {
System.out.println("這裡是子類的執行個體方法m()");
}
static void m2(){
System.out.println("這裡是父類的靜态方法m2()");
}
}
public class Test1 {
public static void main(String[] args) {
A a = new A();
a.m1();
System.out.println();
B b = new B();
b.m1();
System.out.println();
A c = new B();
c.m1();
}
}
輸出結果為:
這裡建構了一個父類對象
這裡是父類的執行個體方法m()
這裡是父類的靜态方法m2()
這裡是父類的執行個體方法m3()
1
這裡是父類的執行個體方法m1()
這裡建構了一個父類對象
這裡建構了一個子類對象
這裡是子類的執行個體方法m()
這裡是父類的靜态方法m2()
這裡是父類的執行個體方法m3()
1
這裡是父類的執行個體方法m1()
這裡建構了一個父類對象
這裡建構了一個子類對象
這裡是子類的執行個體方法m()
這裡是父類的靜态方法m2()
這裡是父類的執行個體方法m3()
1
這裡是父類的執行個體方法m1()
可以看出:
構造順序為
父類屬性初始化-》父類構造方法-》子類屬性初始化-》子類構造方法
而且實際會構造的對象要看聲明的類型,如果是子類就是子類的。
其中
A c = new B();
建構順序為先建構父類,再建構子類。但隻能調用被子類覆寫的方法,而不能調用子類獨用的方法。(在B中設計一個父類沒有的m3方法,然後用c.m3()調用,發現報錯,m3()未被定義。哪怕m3()改為靜态方法也不行)
也就是說隻多了一個被覆寫的方法,其他沒影響。
而且this指的就是this這個詞自己所在的類,而非網上部分文章說的是建立的對象(new後面的)的類,隻是被覆寫的方法除外,隐藏了沒用。而且A中的this去掉也沒有影響。
父類中被覆寫的方法在父類中無法調用,在子類中可以用super調用,其他地方可以通過隻建立父類對象直接調用,用子類間接調用隻能找子類裡用的super方法的。
被隐藏的變量和靜态方法可以在父類中被直接調用,其他和覆寫一緻。
下面可以利用另一端代碼進行練習測試:
class A{
int x = ;//被隐藏
void print(){//被覆寫
System.out.println("這裡是父類方法,x="+x);//父類A的方法中通路的變量必然是A類或A的父類的,不可能通路B類的。
m();//父類A的方法中調用的執行個體方法m()是子類B的,由于發生了覆寫
}
void m(){//被覆寫
System.out.println("這裡是父類的執行個體方法m()");
}
static void m2(){//被隐藏
System.out.println("這裡是父類的靜态方法m2()");
}
}
class B extends A{
int x = ;
void print(){
System.out.println("這裡是子類方法,x="+x);//子類方法通路的變量是子類對象的(當然條件是子類中聲明了這個變量)
System.out.println("這裡是子類方法,super.x="+super.x);//super.x是父類對象的
super.print();//調用父類的print()方法
m();//調用本對象的m()方法
}
void m(){
System.out.println("這裡是子類的執行個體方法m()");
}
static void m2(){
System.out.println("這裡是子類的靜态方法m2()");
}
static void m3(){//靜态與否都沒用
System.out.println("這裡是子類的執行個體方法m3()");
}
}
public class Test{
public static void main(String []s){
A p = new B();
System.out.println(p.x);//通過引用變量p來通路變量或靜态方法,要看p的聲明類型。是以x是A類的。
p.m2();//同上。靜态方法m2()是A類的。
p.print();//通過引用變量p來通路執行個體方法,要看p指向的對象的實際類型。由于覆寫,調用的print()方法是子類的。
p.m3();//報錯The method m3() is undefined for the type A
}
}