java面向對象--對象初始化

重載(Overload)是指在一個類里面,多個方法的名字相同,而參數列表(參數的類型、個數和順序)不同。返回值類型和修飾符與重載無關。解決相同意義的行為使用不同名字的問題。
構造器最大的作用就是在創建對象時執行初始化。
默認構造器又名無參構造器,作用是創建一個默認對象。如果類中沒有任何構造器,則編譯器會自動創建一個默認構造器。如果已經自行定義了任意一個構造器,編譯器就不會自動創建無參構造器。

所有實例共用一份方法,編譯器會把當前對象的引用作為第一個參數傳入方法內部,以區分不同的調用對象。
this:在方法內部使用,this表示對“調用方法的那個對象”的引用。最大的作用就是讓類中的一個方法,訪問該類的另一個方法或屬性。
static方法是沒有this的方法,所以靜態成員不能訪問非靜態成員。
static關鍵字:修飾的成員表明它是屬于類共有的,既可以通過類訪問,也可以通過實例訪問。
在方法內部訪問同一個類的成員,不需要使用this。
如果參數變量和成員變量同名時,可以用this.field=field加以區分。
在構造器中調用構造器:this可以指代重載的其他構造器方法以減少代碼重復。注意此時this(arg)必須作為構造器中的第一句代碼。

復制代碼

public class Teacher {    private String name; 
    private int age;    public Teacher(String name,int age ){       this(name);       this.age=age;
    }    public Teacher(String name){        this.name = name;
    }
}

復制代碼

靜態數據、成員變量及構造器的初始化順序
無繼承時:
假設有個名為Dog的類,創建過程如下:
1.當首次創建類型為Dog的對象時(構造器可以看成靜態方法),或者Dog類的靜態方法/靜態域首次被訪問時,Java解釋器必須查找類路徑,以定位Dog類的編譯代碼(在Dog.class文件中)。 
2.然后載入Dog.class(這將創建一個Class對象),執行有關靜態初始化的動作。因此,靜態初始化只在Class對象首次加載的時候進行一次。 靜態變量和靜態初始塊化塊按定義的順序進行初始化。
3.當用new Dog()創建對象的時候,首先將在堆上為Dog對象分配足夠的存儲空間。 
4.這塊存儲空間會被清零,這就自動地將Dog中的所有基本類型數據設置成了默認值(對數字來說就是0,對布爾型和字符型也相同),而引用則被置成了null。 (默認初始化)
5.執行所有出現于成員變量定義處的初始化動作。(按定義的先后順序進行顯示初始化,包括成員變量和初始化塊
6.執行構造器。
7.對象構造完畢,將地址賦給引用類型變量。

有繼承時:
假設有個名為Golden的類,繼承自Dog,Dog又繼承自Animal,初始化過程如下: 
1.當首次創建類型為Golden的對象時,Java加載器查找Golden類的編譯代碼(在Golden.class文件中)。 
2.Java加載器會加載Golden.class文件,同時根據Golden.class(extends關鍵字)加載其基類Dog.class文件,再根據Dog.class加載根基類Animal.class文件。然后從根基類Animal到基類Dog再到子類Golden依次執行靜態數據的初始化。 (子類的靜態數據在父類的成員變量之前初始化)
3.當你用new Golden ()創建對象的時候,首先將在堆上為Golden對象(包括本類Golden、基類Dog和根基類Animal中的所有成員變量)分配足夠的存儲空間。由于子類的構造器不能訪問父類的private成員,所以必須利用super關鍵字來初始化這部分成員變量。 
4.這塊存儲空間會被初始化默認值即二進制的零。Golden中的所有基本類型數據(包括其基類Dog和Animal中的)設置成了默認值(對數字來說就是0,對布爾型和字符型也相同),而引用(包括其基類Dog和Animal中的)則被置成了null。也就是說在執行任何初始化代碼之前,所有實例變量都已設置完默認的初值。
5.執行根基類Animal中所有成員變量的初始化動作。 
6.執行基根類Animal構造器。 
7.執行基類Dog中所有成員變量的初始化動作。 
8.執行基類Dog構造器。 
9.執行導出類Golden中所有成員變量的初始化動作。 
10.執行導出類Golden構造器。
簡單來說,就是從子類到基類依次加載類的class文件,然后從根基類到子類依次進行靜態數據的初始化。再為對象分配存儲空間,在存儲空間清零后,依次從父類到子類進行實例初始化(包括成員變量初始化,調用構造器2步)。

Java在開發者沒有定義別的super語句時會自動在子類的構造器中插入對父類構造器的調用,該調用并不是簡單地執行父類構造函數,具體順序如下(省略類初始化過程):
1、進入當前類的構造方法,調用super()(會被編譯器改名為<init>,不執行別的代碼)直接進入父類構造方法,并遞歸到java.lang.Object類構造方法。
2、執行java.lang.Object類的初始化,順序為先初始化成員變量/初始化塊(按照定義順序),再調用構造方法(super部分不再執行)進行初始化。
3、運用步驟2的方法初始化java.lang.Object類的直接子類,并遞歸這個過程到當前類。

 

注意:
對象只能通過new constructor()的方式創建,所以編譯器在程序員沒有編寫構造器時會提供默認的無參構造器。Constructors are meant for initializing the members of objects.
類的加載發生在:new 對象時,訪問類的靜態數據時,main方法所在的類在運行java應用時。而在類被加載時就會初始化靜態數據。
對象會取得所有實例變量所需的空間,包括一路繼承下來的東西。
在創建對象時,所有父類的構造函數都會被執行:構造函數在執行的過程中,第一件事是調用它父類的構造函數(編譯器通過super調用或開發者自己調用有參數的父類構造函數),直到連鎖反應到Object這個類為止,即“構造函數鏈”。
創建對象過程中,子類對象可能訪問從父類繼承下來的數據,所以super()必須是構造函數的第一個語句,父類構造函數必須在子類構造函數之前結束。
this(..)指代當前類的其他構造函數,也必須是構造函數中的第一句語句,所以super()和this()只能二選一。
每個對象除了保存類的實例變量之外,還保存著實際類信息的引用,存放類信息的內存區,在Java中稱為方法區。
虛方法表,就是在類加載的時候,為每個類創建一個表,這個表包括該類的對象所有動態綁定的方法及其地址,包括父類的方法,但一個方法只有一條記錄,子類重寫了父類方法后只會保留子類的。

復制代碼

class Glyph {    void draw() {
        System.out.println("Glyph.draw()");
    };
    Glyph() {
        System.out.println("Glyph() before draw()");
        draw(); // 調用重寫了的子類型方法
        System.out.println("Glyph() after draw()");
    }
}class RoundGlyph extends Glyph {    private int radius = 1;
    RoundGlyph(int r) {
        radius = r;
        System.out.println("RoundGlyph.RoundGlyph(), radius = " + radius);
    }    void draw() {
        System.out.println("RoundGlyph.draw(), radius = " + radius);
    }
}public class PolyConstructors {    public static void main(String[] args) {        new RoundGlyph(5);
    }
}/*Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5*/


來源:博客園

上一篇: JavaEE開發之Spring中的條件注解、組合注解與元注解

下一篇: java面向對象--繼承與多態

分享到: 更多
乐和彩官网 全天北京赛场pk10数据计划 澳客彩票网 pk10最牛稳赚模式8码计划 北京pk10技巧压6法 全天pk10 可以玩天津时时 欢乐生肖平台哪个好 麻将28杠比大小规则 gt时时彩地址 体球比分即时足球比分 足球即时比 二人斗地主邀请好友 牌九至尊最新版下载 篮球赛 双色球机选复式号码投注