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的构造方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值