簡體   English   中英

當我們創建一個對象時,對象的創建和構造函數的執行是否同時發生?

[英]when we create an object ,do creation of object and the execution of constructor happens at the same time?

當我們創建一個對象時,對象的創建和構造函數的執行是同時發生還是創建第一個對象然后執行構造函數?

其用赫伯特·希爾德(Herbert Schildt)寫道:“一旦定義,在創建對象之后, 操作符完成之前,構造函數將立即自動調用”。 我的隊列是,如果new運算符尚未完成其內存分配,那么如何在new完成之前調用構造函數,因為只有在創建對象之后才調用new編寫的構造函數。

JLS的12.5節提供了詳細信息。 它的基本內容是:

  • 分配了內存空間(所有字段均具有相關類型的默認值,例如null或0)
  • 指定的類的構造函數被調用,它將立即鏈接到同一類中的另一個構造函數或超構造函數
  • 最終,鏈到達java.lang.Object
  • 在返回的每個構造函數鏈中,實例變量都是根據其字段初始化器(如果有的話)進行初始化的(並且僅當我們未鏈接到同一類中的另一個構造函數時),然后構造函數的主體代碼被執行。 然后返回到調用構造函數,依此類推。

當然,JLS會更詳細,包括內存不足或構造函數主體引發異常的情況。

但是,構造函數每一位的計時很重要:

  • 鏈接到此/超級構造函數
  • (隱式)如果鏈是超類構造函數,則將初始值分配給字段
  • 構造體

重要的是要了解,如果超級構造函數調用一個覆蓋方法來顯示字段的值,那么它將尚未通過字段初始化程序。 因此,您可以看到該字段的默認值,而不是初始化程序期望的值。 例如:

class Bar extends Foo {
    private String name = "fred";

    @Override public String toString() {
        return name;
    }
}

如果Foo構造函數調用toString() ,則它將為null而不是"fred"

(如果namefinal ,則在toString()中將其視為常量,並且發生其他事情,但這是另一回事。)

new運算符通過依次執行一些操作來創建新對象:它根據需要為該對象分配內存(此操作可能會觸發JVM中的其他操作),它執行被調用的構造函數中定義的代碼,最后返回調用者,並引用新創建的對象。 值得注意的是,構造函數調用發生在所有變量在當前類中被默認初始化之后,並且相同的序列發生在層次結構中最頂層的類直到當前類(因此Object()首先執行等)。

因此,從技術上講,構造函數在新創建的對象(即為其分配的內存空間)上執行,因此它永遠不會在尚未分配或正在分配的內存上執行。

當您調用new ,將在對象的堆上分配內存,包括初始化為默認值的變量。 如果將值作為構造函數參數提供,則使用這些值。

一旦構造函數完成初始化,就在堆棧上創建分配給它的變量,並以堆中對象的地址為其值。

我建議您觀看本斯坦福大學的講座 ,在其中進行了足夠詳細的解釋,以便任何人都可以理解。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM