2016-08-04 46 views
1

代碼:爲什麼可以重寫方法但變量不能?

public class ClassTest { 

     public static void main(String args[]) { 
      test1 cc = new test2(); 
      System.out.println(cc.A); 
      System.out.println(cc.B); 
      cc.method1(); 
      cc.method2(); 
     } 

} 

class test1 { 
     static int A = 2; 
     int B = 5; 

     void method1() { 
      System.out.println("Inside method 1 test1"); 
     } 

     static void method2() { 
      System.out.println("Inside method2 test1"); 
     } 
} 

class test2 extends test1 { 
     static int A = 4; 
     int B = 6; 

     void method1() { 
      System.out.println("Inside method 1 test2"); 
     } 

     static void method2() { 
      System.out.println("Inside method 2 test2"); 
     } 
} 

OUTPUT:

內部方法1 TEST2

裏面方法2 TEST1

問:

爲什麼只有方法覆蓋,但變量保持不變?

此行爲是否有名稱? (如方法的「覆蓋」)

+0

問題「爲什麼」很棘手 - 這是因爲語言的設計者決定像這樣做,原因是簡單,高效,清晰,等等。 – RealSkeptic

+0

這就是語言的設計。至於爲什麼,你不得不問Java的發明者。 –

+0

你正在調用一個實例的靜態方法? ''static void method2()' - >'cc.method2();' – Fildor

回答

1

這裏發生了什麼事,你已經使用type1引用指向的test2一個實例。你可以這樣做,因爲test2是一種test1 - 這叫做多態性

test2test1衍生,因此當你創建類型的對象test2你將基本上已經創建兩個對象,test2test1(不會駐留在堆作爲自主對象)。

JVM將從其引用訪問對象的字段(因爲Java是靜態類型語言)。

所以,儘管test2隱藏test1,這兩個領域在試圖從test1參考Java訪問他們自動進入test1

這是關於它的領域。

當處理方法時,我們有一個更復雜的問題。方法是改寫,因此,當方法表建立時,方法test2覆蓋test1的方法。但是,靜態方法不是實例方法。

因此,當試圖訪問來自test1參考的test2的靜態方法method2時,您「濫用」了代碼。你應該打電話給test1.method2()或者,如果你想訪問靜態方法test2你應該使用test2.method2()

希望我解釋的不夠好......

2

覆蓋方法意味着讓相同的方法調用執行另一個方法體(在子類中)。

對於變量「覆蓋」是不必要的:你可以用覆蓋這個變量的值。

在同名子類中聲明變量隱藏父類變量並引入了一個附加字段。

對於方法是可重寫的,需要一種特殊的機制,使得在碼的地方可能會調用實際的類對象的指定方法。這與訪問字段相反。

1

在上述例子中,你正在創建基類時將採取的基準值A = 2,B = 5,它將分配內存also.so當倍率到派生類,基礎類變量隱藏派生類的變量值這就是爲什麼它無法在派生類中重寫的原因。

0

在行:System.out.println(cc.A);
這不是調用靜態成員的正確方法,你應該總是使用類的名稱,例如:System.out.println(test1.A);

按Java規範中,實例變量在擴展時不會被子類從超類中覆蓋。
變量是靜態的還是非靜態的。只有方法可以被重寫。 這就是爲什麼cc.A & cc.B輸出是從test1

對於方法覆蓋:
代碼cc.method1();這裏overrriding發生,對象類型(類即實例)實際上確定哪些方法是在選定的運行時,通過此對象聲明new test2()在此代碼中:test1 cc = new test2();
編譯器首先檢查test1類中的方法,然後檢查text2類中的方法,如果所有簽名(參數,返回類型等)都相同它調用子類方法 ,因爲它重寫基類方法,因爲實際對象是類test2

對於靜態方法: 靜態方法不能被重寫,因爲方法覆蓋僅發生在動態的上下文中的方法(即,運行時)的查找。
靜態方法(通過它們的名字)被靜態地查找(即在編譯時)。
這就是爲什麼輸出是從類test1

對於Java中的「靜態方法」,確切的調用方法是在編譯時確定的。
您明確指定要執行靜態方法的類的名稱

相關問題