java學習筆記12——構造器

   Java中子類可以繼承父類的屬性和方法,那麼子類對象就可以直接使用父類對象的屬性和方法,實現機制就是,當某個子類對象實例化的時候,會首先實 例化一個其父類對象,但這個父類對象對外不可見,只能通過子類中的super來訪問;以此類推,父類對象初始化前又會先初始化它的父類對象......直 至初始化Object對象爲止。這樣的效果就是,新建一個類的實例實際上得到的是一個對象的“鏈條”,通過關鍵字super連接的對象鏈條。子類對象就可以通過super來訪問到所有它繼承到的東西。

        爲了實現這樣的初始化動作,應該在每個類的構造器中所有代碼的前面先初始化這個類的直接父類對象。

        但是事實上,我們平時寫代碼的時候,構造器中多數沒有寫過父類對象初始化的語句,甚至很多時候,連構造器都不寫。但是程序依然正常運行,爲了一探究竟,我用DJ Java Decompiler工具來反編譯class文件,查看內部細節。

Parent類,沒有寫任何構造器,

  1. package  aa;  
  2. public   class  Parent {  
  3.       
  4. }  
 

        反編譯該類文件,可以看到,Java編譯時看到程序沒有寫任何構造器,就會自動加上一個“空”的無參構造器,(若程序中已定義構造器,不論有參無參,這個“空”的無參構造器就不會自動產生)

  1. // Decompiled by DJ v3.9.9.91 Copyright 2005 Atanas Neshkov  Date: 2010-4-2 14:44:26   
  2. // Home Page : http://members.fortunecity.com/neshkov/dj.html  - Check often for new version!   
  3. // Decompiler options: packimports(3)    
  4. // Source File Name:   Parent.java   
  5. package  aa;  
  6.   
  7. public   class  Parent  
  8. {  
  9.     public  Parent()  
  10.     {  
  11.     }  
  12. }  
 

我們現在定義一個子類Son,繼承這個Parent類

  1. package aa;  
  2. public   class  Son extends Parent {  
  3.     public  Son(String s){  
  4.     }  
  5. }  
 

這裏子類Son的構造器中沒有寫任何的實例化父類的語句,反編譯的程序中也沒有,但是我們查看class文件內容

  1. // Decompiled by DJ v3.9.9.91 Copyright 2005 Atanas Neshkov  Date: 2010-4-2 14:53:01   
  2. // Home Page : http://members.fortunecity.com/neshkov/dj.html  - Check often for new version!   
  3. // Decompiler options: packimports(3) disassembler    
  4. // Source File Name:   Son.java   
  5. package  aa;  
  6.   
  7. // Referenced classes of package aa:   
  8. //            Parent   
  9. public   class  Son  extends  Parent  
  10. {  
  11.     public  Son(String s)  
  12.     {  
  13.     //    0    0:aload_0            
  14.     //    1    1:invokespecial   #8   <Method void Parent()>   
  15.     //    2    4:return             
  16.     }  
  17. }  
 

        可以看到在Son的構造器內部,並不是空的,第二條的指令就是調用父類的構造器 Method void Parent(),相當於Son的構造器裏面寫了一條super(); 這裏編譯器自動加的是父類的無參構造器,而不管父類究竟是否有無參構造器,這也正是父類沒有無參構造器(程序員寫了一個帶參數的構造器,編譯器就不再自動 添加一個“空”的無參構造器)時,子類構造器中若不顯示初始化父類對象,編譯器就會報錯的原因。(因爲子類構造器中沒有初始化父類對象的語句,所以編譯器 自動爲子類構造器添加了一個調用父類無參構造器的指令,但是父類沒有無參構造器,找不到指定的方法,便會報錯)

        所以正常情況下,我們可以不寫構造器(編譯器會幫我們加一個),在構造器中我們也不必顯示初始化父類對象(編譯器會幫我們調用父類無參構造器),但這不代表程序中就真的可以沒有。


      當創建一個個對象時,系統會該對象的屬性默認初始化,基本類型屬性的值爲0(數值類型),false(布爾類型),把所有的引用類型設置爲null.

      構造器可以改變這種默認的初始化

      構造器的作用:是創建java對象的重要途徑,是不是說構造器完全負責創建java對象?????

                          答:是創建java對象的重要途徑,通過new關鍵字調用構造器時,構造器也確實返回了該類的對象,但這個對象並不是完全由構造器負責創建的。

 

      系統調用構造器時的執行過程分析:

      當調用構造器時,系統會爲該對象分配內存空間,並對該對象進行默認的初始化,這個對象已經產生了,---------------------------------------》這些操作在構造器執行 之前已經完成了。也就是在構造器的執行體執行之前,系統已經創建了一個對象,只是這個對象還不能被外部程序訪問,只能在構造器中,通過this引用它,當構造器的執行體結束之後,這個對象作爲該構造器的返回值被返回,同時還賦給另一個引用類型的變量。從而外部程序可以訪問該對象。

       個人理解:構造器作用,1.創建java對象的重要途徑。2.對系統產生的對象初始化 。3.並將該對象作爲返回值返回,是外部程序可以訪問

 

     一個類中構造器之間的相互調用(一個構造器調用另一個構造的初始化代碼):構造器不能直接調用,必須使用new關鍵字調用,但是會導致系統重新創建一個對象。爲了避免重新創建對象,可以使用this關鍵字來調用相應的構造器

     this調用另一個構造器,只能在構造器中使用,而且必須作爲構造器語句的第一條語句。

    super是java提供的一個關鍵字,是直接父類的引用。java程序創建某個類得對象時,會隱式的創建該類的父類對象,只要有一個子類對象存在,則一定存在一個與之對應的父類對 象。

     this,super:不能出現在static修飾的方法中,static修飾的方法是屬於類得,該方法的調用者是類而不是對象,也就不存在對應的對象以及父對象了,所以this,super引用就失去了意義。

    使用super調用父類構造器必須出現在子類構造器的第一行。所以this調用和super調用不會同時出現。

    子類構造器調用父類構造器的幾種情況

       1.子類構造器的執行體的第一行用super顯式調用父類構造器,系統將根據super 調用裏傳入的實例列表調用父類對應的構造器

       2.子類構造器執行體的第一行是this顯式調用本類中重載的構造器,系統根據this調用裏傳入的實參列表調用本類中另一個構造器,執行本類中另一個構造器時,既會調用父類的構造器。

      3.子類構造器中既沒有this,也沒有super,系統將會在執行子類構造器之前隱式調用父類無參的構造器

       不管上面哪種情況,當調用子類構造器來初始化子類對象時,父類構造器總會在子類構造器之前執行,不僅如此,執行父類構造器時,系統會再次上溯執行其父類的構造器。。。。以此類推。創建任何java對象,最先執行的總是java.lang.Object類得構造器


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章