Thinking in Java之對象的創建過程

引用Thinking in Java中的一段話:

To summarize the process of creatingan object, consider a class called Dog:

1.  Even though it doesn’t explicitly use the static keyword, the constructor is actually a

staticmethod. So the first time an object of type Dogis created, orthe first time a

staticmethod or static field of class Dogis accessed, the Java interpreter must

locate Dog.class, which it does by searching through the classpath.

2.  As Dog.classis loaded (creating a Classobject, which you’ll learn about later), all of

its staticinitializers are run. Thus, static initialization takes place only once, as the

Classobject is loaded for the first time.

3.  When you create a new Dog( ), the construction process for a Dogobject first

allocates enough storage for a Dogobject on the heap.

4.  This storage is wiped to zero, automatically setting all the primitives in that Dog

object to their default values (zero for numbers and the equivalent for booleanand

char) and the references to null.

5.  Any initializations that occur at the point of field definition are executed.

6.  Constructors are executed. As you shall see in the Reusing Classeschapter, this might

actually involve a fair amount of activity, especially when inheritance is involved.


     爲了總結創建對象的過程,想象一個叫做Dog的類:

      1、雖然並沒有顯示的用static關鍵字來說明,但是類的構造方法其實是一個靜態的(static)的方法。所以當Dog類的對象第一次被創建時,或者Dog類的靜態方法或者靜態屬性被訪問時,JAVA編譯器會在classpath下查找Dog類。

      2、當類被加載到內存的時候,它所有的靜態成員就會被初始化。因此,靜態初始化只會發生一次,也就是類第一次被加載的時候。

      3、當我們用new Dog()創建一個對象時,Dog對象的構造過程首先在堆中爲Dog對象分配足夠的存儲空間。

      4、這個存儲空間被擦除爲0,自動把Dog對象的原始類型的成員變量設置爲默認值(數字類型的設置爲0,布爾類型和char類型也設上相應的默認值),引用類型設爲null。

      5、所有的初始化都會發生在屬性定義被執行的那一刻。

      6、執行構造方法。如果涉及到繼承的話,這裏還會涉及到另外一些活動。

       下面還是引用Thinking in Java中的一個例子來說明在在繼承關係的程序中對象的創建過程。

/: reusing/Beetle.java 
// The full process of initialization. 
import static net.mindview.util.Print.*; 
class Insect { 
private int i = 9; 
protected int j; 
Insect() { 
print("i = " + i + ", j = " + j); 
j = 39; 
} 
private static int x1 = 
printInit("static Insect.x1 initialized"); 
static int printInit(String s) { 
                                                           
print(s); 
return 47; 
} 
} 
public class Beetle extends Insect { 
private int k = printInit("Beetle.k initialized"); 
public Beetle() { 
print("k = " + k); 
print("j = " + j); 
} 
private static int x2 = 
printInit("static Beetle.x2 initialized"); 
public static void main(String[] args) { 
print("Beetle constructor"); 
Beetle b = new Beetle(); 
} 
} /* Output: 
static Insect.x1 initialized 
static Beetle.x2 initialized 
Beetle constructor 
i = 9, j = 0 
Beetle.k initialized 
k = 47 
j = 39 
*///:~ 

      當我們運行Beetle類的時候(java Beetle),首先發生的事情是訪問它的main方法,因此類加載器會找到這個類(其實就是Beetle.class文件),在加載這個類的過程中,加載器發現它有一個父類,此時它又轉去加載它的父類。

      如果它的父類還有一個父類,父類的父類又會被加載,如此下去。最後,最上層的那個父類的靜態初始化被執行,然後是下一層的靜態初始化,如此下去,最後到Beetle類的靜態初始化。這個很重要,因爲子類的靜態初始化可能會依賴於父類。

      到此爲止,所有必要的類都被加載上了,因此對象就可以創建了。所以Beetle的所有原始類型屬性被賦上設置的值,引用類型被賦爲null(在這之前首先要把存儲空間都擦除爲二進制的0),然後就會調用構造方法,調用構造方法的時候會首先自動調用父類的構造方法,調用父類構造方法之前會初始化父類的屬性,調用完父類構造方法之後再接着執行Beetle的構造方法。

發佈了31 篇原創文章 · 獲贊 1 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章