多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
Java程序在启动和运行时,需要首先完成初始化的工作。在涉及到继承、static成员变量等因素时,初始化的顺序就复杂起来。下面以一个例子说明继承时的Java初始化顺序。 ## 例子: ~~~ class Insect{ private int i = 9; protected int j; Insect(){ System.out.println("i = " + i + ", j = " + j); j = 39; } private static int x1 = printInit("static Insect.x1 initialized"); static int printInit(String s){ System.out.println(s); return 47; } } public class Beetle extends Insect { private int k = printInit("Beetle.k initialized"); public Beetle(){ System.out.println("k = " +k); System.out.println("j = " + j); } private static int x2 = printInit("static Beetle.x2 initialized"); public static void main(String[] args){ System.out.println("Beetle constructor"); Beetle b = new Beetle(); } } ~~~ 输出: ~~~ 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()(一个static方法), 于是加载器开始启动并找出Beetle类的编译代码(在名为Beetle.class的文件中)。在对它进行加载的过程中, 编译器注意到它有一个基类(这是由关键字extends得知的),于是它继续进行加载。不管你是否打算残生一个该基类的对象,这都要发生( 请尝试将对象创建代码注释掉,以证明这一点)。如果该基类还有其自身的基类,那么第二个基类就会被加载,如此类推。 接下来,根基类中的static初始化(在此例中为Insect)即会被执行,然后是下一个导出类,以此类推。 这种方式很重要,因为导出类的static初始化可能会依赖于基类static成员能否被初始化。 至此为止,必要的类都已加载完毕,对象就可以被创建了。首先是基类对象的创建,然后是下一个导出类对象创建,以此类推。 对于每一个对象的创建,首先对象中所有的基本类型都会被设为默认值,对象引用被设为null——这是通过将对象内存设为二进制零值而一举生成的。 然后对象中的成员的显示的初始化被执行。然后构造器会被调用,对象创建完毕。 (以上例子和说明来自于Java编程思想第四版,说明部分有一些是自己修改的,仅用于学习交流之用)