java 多態,和方法覆蓋分析

來源:互聯網
上載者:User
 多態 (Polymorphism) 大家應該都不陌生,它是我們開發物件導向系統的“老朋友”了 。但是老朋友也會有“煩心”的時候啊,呵呵。有時候 不注意,還真會被它難到。譬如下面這個例子(thank Hayden)。大家可以先不看下面的答案,在自己腦海中運行一道,看看自己想的跟實際結果是否 相符。public class Polymorphism{
 public static void main(String[] args) {
  A b = new B();
  b.fb();
 }
}class A {
 public A(){
  
 }
 public void fa() {
  System.out.println("CLASS A :Function fa Runing......");
 }

 public void fb() {
  System.out.println("CLASS A :Function fb Runing......");
  fa();
  System.out.println("CLASS A :Function fb Stop......");
 }
}class B extends A {
 public B(){
 }
 public void fa() {
  System.out.println("CLASS B :Function fa Runing......");
 }

 public void fb() {
  System.out.println("CLASS B :Function fb Runing......");
  super.fb();
  System.out.println("CLASS B :Function fb Stop......");
 }
}

下面是它的運行結果:CLASS B :Function fb Runing......
CLASS A :Function fb Runing......
CLASS B :Function fa Runing......
CLASS A :Function fb Stop......
CLASS B :Function fb Stop......

   怎麼樣,猜對結果了嗎?如果結果跟你想象的一模一樣,那麼恭喜你,你對多態已經有初步瞭解了,起碼在文法層次上是比較熟悉了。但是,千萬不要“洋洋得意”,你可否解析結果為什麼會是這樣嗎?我們可以先來梳理一下程式流程:
   1、運行main函數,建立B對象,調用B的方法fb,於是列印出"CLASS B :Function fb Runing......",都在情理之中。
   2、執行super.fb(),調用父類A的方法fb,首先列印出"CLASS A :Function fb Runing......",預料之中
   3、執行方法fa(),列印出"CLASS B :Function fa Runing......",呃?奇怪了,為什麼不是執行A的方法fa(),而是子類B中的fa()呢?當前被執行的是類A的方法,那麼虛擬機器找到的應該是A類的Method Table,找到的應該是A類的方法fa()啊?難解~
   4、列印"CLASS A :Function fb Stop......",返回
   5、列印"CLASS A :Function fb Stop.....",返回,程式結束。
  現在問題清楚了,就是虛擬機器在執行類A方法的時候尋找的Method Table竟然是子類B的。為什麼呢?其實,只要我們清楚java方法調用的方 式,這個問題就迎刃而解了。在Java虛擬機器中,每啟動一個新的線程,虛擬機器都會為它分配一個Java棧,而每當線程調用一個java方法時,虛擬機器就會 在該線程的java棧中壓入一個新幀,用以儲存參數,局部變數等資料。我們將這個正在被執行的方法稱為該線程的當前方法,其相應的棧幀為當前幀。
    好了,當我們調用一個方法時,我們需要往當前幀中壓入哪些參數呢?簡單,方法的參數列表中不是都說得清清楚楚的嗎?嗯,對於C語言來說,這個說法 是正確的,但是對於諸如C++,Java,Python等物件導向語言來說,卻是不對的。大家還記得那個"this"指標嗎?!不錯,在Java中,所有的執行個體方法(Instance Method)調用的時候都會把當前對象壓入當前幀中,Java虛擬機器正是通過這個參數來決定當前所使用的類(通過判斷該對象的類型)
    在上面的例子中,main中調用b.fb()時,壓入的當前對象自然是B類對象,我們記為b。在B的fb()中調用super.fb()時,壓入 的就是剛剛壓入的對象,也就是b了。同樣,在A的fb中調用fa()時,壓入的也是b。因此,在使用 invokevirtual指令調用fa()時,找 的就是B的方法表(當前對象b的類型為B),也就執行了類B的fa了。
    這種現象在建構函式中特別常見,因為建構函式中會隱含使用調用父類的建構函式的,如果在父類的建構函式中調用了執行個體方法(如 A的fa),而在子 類中又覆蓋了這個執行個體方法(如 B的fa),那麼得到的結果往往不是我們所要的。因此,我們最好不要在建構函式中使用多態方法,不然,Debug會很痛苦 的:)

轉http://hi.baidu.com/daping_zhang/blog/item/2bba09fa10bc489759ee90bc.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.