2008-10-20 67 views
9
  1. 當一個對象在Java中被實例化時,真正進入內存的是什麼?
  2. 是否包含父構造函數的副本?
  3. 爲什麼隱藏數據成員在投射時的行爲與重寫的方法不同?

我明白爲了讓你正確使用這些東西而給出的抽象解釋,但JVM是如何真正做到的。Java實例化

回答

17

當一個對象被實例化,只有非靜態數據實際上是「創建」是,與該參考沿創建它的對象的類型。

沒有任何方法被複制。

創建它的類的「引用」實際上是一個指針調度表。每個可用於該類的方法都有一個指針。指針始終指向方法的「正確」(通常是對象樹中最低/最具體的)實現。

這樣,如果您對另一個方法有頂級調用,但其他方法已被覆蓋,則將調用重寫的方法,因爲這是表中指針指向的位置。由於這種機制,它不應該花費更多時間來調用一個被重寫的方法而不是一個頂層的方法。

指針表+成員變量是類的「實例」。

變量問題與完全不同的機制「名稱空間」有關。變量不是「Subclassed」(它們不進入調度表),但公共變量或受保護的變量可以被局部變量隱藏。這一切都由編譯器在編譯時完成,並且與運行時對象實例無關。編譯器確定你真正想要的是哪個對象,並在你的代碼中提供對它的引用。

範圍規則通常傾向於「最近的」變量。任何遠離相同名稱的東西都會被忽略(隱藏)以支持更接近的定義。如果你有興趣,所有的「OBJECTS」都被分配到「堆」上(事實上它比真正的堆更有效率,更漂亮,但是同樣的概念。)變量總是指針 - Java永遠不會複製一個對象,你總是複製一個指向該對象的指針。方法參數和局部變量的變量指針分配在堆棧上完成,但即使在堆棧上創建了變量(指針),它們指向的對象仍然不會分配到堆棧上。

我很想寫一個例子,但這已經太長了。如果你想讓我用一個擴展關係來輸入一些類,以及它們的方法和數據如何影響代碼的生成,我可以......請問。

+0

你還願意寫一個例子嗎?如果是的話,請這樣做。 – Touchstone 2015-06-09 08:17:40

0
  1. 從堆中分配內存以保存對象和它的超類的所有實例變量和特定於實現的數據。特定於實現的數據包括指向類和方法數據的指針。

  2. 對象的實例變量被初始化爲默認值。

  3. 調用了大多數派生類的構造函數。構造函數的第一件事就是調用它的大寫構造函數。這個過程一直持續到java.lang.Object的構造函數被調用,因爲java.lang.Object是java中所有對象的基類。

  4. 在執行構造函數的主體之前,會執行所有實例變量初始值設定項和初始化塊。然後執行構造函數的主體。因此,基類的構造函數首先完成,大多數派生類的構造函數最後完成。

+0

所有這些都是一些有趣的信息,但我傾向於認爲Bill未回答的部分也沒有回答這個問題。 – chiccodoro 2014-08-25 10:19:28