JavaSE笔记之<初始化顺序深入>

来源:互联网 发布:淘宝加盟诈骗罪 编辑:程序博客网 时间:2024/05/16 04:45

先说加载的概念:类的代码在初次使用时才加载,这通常指加载发生于创建类的第一个对象之时,但是当访问static域或static方法(比如访问JVM访问main方法时,除访问编译器常量外,编译器常量不用初始化就知道其值),也会发生加载。

所有的static对象和static代码段都会在加载时依程序中的顺序(即定义类时的书写顺序)而依次初始化(即类加载只有两个要执行的,①static对象和②static代码块执行初始化)。当然,定义static的东西只会被初始化一次。

必要的类加载完毕,对象就可以被创建了。大的步骤有两个:1.类加载 2.对象创建

对象创建的时候有4个步骤:①在堆上为为对象分配足够的存储空间;②这块存储空间会被清零;③执行所有字段定义的初始化和实例初始化动作(根据顺序执行);④执行构造器(构造器最后执行,此时对象创建完毕)。


涉及到继承时(由于任何类都是继承的,所以只考虑继承情况),初始化的顺序是按照如下步骤来的:

①父类和子类static对象和static代码块初始化

②子类对象、父类对象(super)存储空间清零。

②父类初始化完成(字段的初始化和实例初始化动作、构造器)

③子类初始化完成(字段的初始化和实例初始化动作、构造器)


当调用子类static方法或者访问子类static数据时,加载器开始启动并找出子类的编译代码(存在class文件中),在对其加载过程中注意到它有一个父类(通过extends关键字得知),于是它继续进行加载,如果该父类还有父类,则继续加载,如此类推。接下来,根基类中的static初始化,然后是下一个子类,以此类推。此时类加载完毕。



图转载自:http://www.cnblogs.com/miniwiki/archive/2011/03/25/1995615.html


实例初始化的用途:保证无论调用了哪个显式构造器,某些操作都会发生。

静态块的用途:和静态初始化动作一样,当首次加载类或者生成这个类的对象或者访问该类的静态数据成员时,静态块执行且仅一次。一般类已加载就要运行的代码放在静态块里。



附:

为了使用类而做的准备工作实际包含三个步骤:

1.加载,这是由类加载器执行的。该步骤将查找字节码(通常在classpath所指定的路径中查找,但并不是必需的),并从这些字节码中创建一个Class对象。

2.链接。在链接阶段将验证类中的字节码,为静态域分配存储空间,并且如果必需的话,将解析这个类创建的对其他类的所有引用。

3.初始化。如果该类具有超类,则对其初始化,执行静态初始化和静态初始化块。

使用.class来创建Class对象的引用时,不会自动地初始化该Class对象,而是初始化被延迟到了对静态方法(构造器隐式地是静态的)或者非编译器常数静态域进行首次引用时执行。而Class.forName()方法就会立即进行初始化。

注:static final值是编译器常量,不需要进行初始化就可以被读取,但如果只是将一个域设置为static和final的,不一定是编译器常量,比如static final x = new Random(47).rand.nextInt(100); 需要运行。如果一个static域不是final的,那么在对它的访问时,总是要求在它被读取之前,要先进行链接和初始化。


0 0