周末闲来无事,做个小例子去看一下JAVA代码初始化的过程
JAVA代码初始化分为两个步骤:类初始化,对象初始化。
类初始化
1 类初始化是指类加载器将类加载到内存时,对类成员的初始化过程(其中包括static修饰的变量)。
2 对于加载完的类,它的类变量都会赋一个默认值,即使你定义时就赋值了。
3 例如int类型就是0,引用类型就是null。
对象初始化
1 其实和类初始化差不多,但是他通过构造函数对对象进行了赋值
其实简单来说
类初始化做了2件事情:1 把所有属性全部赋值为0或者NULL,2 然后给静态变量进行赋值
对象初始化做了1件事情:1 执行构造函数给普通变量赋值或者静态变量赋值(每次NEW 对象时是不执行静态代码块的)
**需要注意的是执行顺序,构造函数会先执行,静态代码块后执行。
例子1 初始化
public class JvmTest { private JvmTest JvmTest ;//private JvmTest jvmTest=null private int count1; //private int count1=0; private static int count2;//private int static=0; public static void main(String[] args) { System.out.println("count1=" + new JvmTest().count1); System.out.println("count2=" + new JvmTest().count2); System.out.println("JvmTest=" + new JvmTest().JvmTest); } }
执行结果
count1=0 count2=0 JvmTest=null
------------------------------------------------------------------------------------------------------------------------------------
例子2 初始化+赋值的过程
如下这样的代码
public class JvmTest { private static JvmTest JvmTest= new JvmTest(); private int count1=5; private static int count2=5; }
可以理解为
public class JvmTest { private static JvmTest JvmTest; private int count1; private static int count2; static{ System.out.println("static init---------------"); count2=5; JvmTest=new JvmTest(); } JvmTest(){ System.out.println("constrctor init---------------"); count1=5; } public static void main(String[] args) { System.out.println("count1=" + JvmTest.count1); System.out.println("count2=" + JvmTest.count2); System.out.println("JvmTest=" + JvmTest.JvmTest); } }
执行结果
static init--------------- constrctor init--------------- count1=5 count2=5 JvmTest[email protected]
初始化的过程会将定义的属性先赋值为0或者NULL,然后再在构造函数和静态代码区中进行正式的赋值
例3 初始化 static和constructor的初始化顺序为,先执行构造函数块,再执行static。
public class JvmTest { private static JvmTest JvmTest = new JvmTest(); private int count1 =5; private static int count2= 5; static{ System.out.println("static init"); count2++; System.out.println(count2); } JvmTest(){ System.out.println("constructor init"); count1++; count2++; System.out.println(count1); System.out.println(count2); } public static void main(String[] args) { System.out.println("类初始化完成"); } }
执行结果(第一步是类初始化属性为0或者为NULL),第二步对象初始化在构造函数和静态代码区中进行赋值
constructor init//执行了 count=5;count1++;count2++ 6 1 static init//执行了count2=5;count2++ 6 类初始化完成
最后一道思考题
package test.test; import org.junit.Test; public class JvmTest { private static JvmTest JvmTest = new JvmTest(); private int count1 = 5; private static int count2 = 5; static { System.out.println("static init"); count2++; } JvmTest() { System.out.println("constructor init"); count1++; count2++; } public static void main(String[] args) { System.out.println("count1=" + new JvmTest().count1); System.out.println("count2=" + new JvmTest().count2); System.out.println("JvmTest=" + new JvmTest().JvmTest); } }
constructor init static init constructor init count1=6 constructor init count2=8 constructor init JvmTest[email protected]
大致步骤为
第一步类初始化后静态count2的值为6。其他的无视
第二步 new JvmTest时会允许构造函数,每次都会执行count1=5;count1++;count2++; 而不会执行static了。
答案
count2是静态变量,打印输出count2是在第二次NEW的时候输出的,所以是初始化的6和2次++的过程,答案为8
count是类的属性,所以每次都是count=5,count++,答案为6
最后的总结
1 JAVA代码初始化的过程是给属性初始化0或者NULL
2 执行构造函数为普通属性赋值
3 执行静态代码区,为静态变量赋值
综上所述,初始化一个JAVA类代码会包含执行3个过程---》属性初始化+通过执行构造函数为普通变量赋值+通过执行静态代码区为静态变量赋值
如果我们NEW一个对象的过程呢?
1 初始化普通属性(非static变量)
2 执行构造函数为普通或者静态属性赋值
从这里看出,NEW的过程不会在允许static的代码块了,只会允许构造函数。
JAVA类的加载过程