《Java编程思想》学习01:普通类的初始化加载顺序分析
本文根据控制变量法,分析普通类(没有extends,implement)初始化的加载顺序;
参考《Java编程思想》第五章
源码
StaticClass1类
package com.tyj.study.thinkinjava; /* * *@Description: *@Author:TYJ *@Date: create in 2019/7/9 17:22 */ public class StaticClass1 { { System.out.println("我是StaticClass1的普通代码块"); } static{ System.out.println("我是StaticClass1的静态代码块"); } static String staticData = staticMethod(); private static String staticMethod(){ System.out.println("我是StaticClass1的静态方法"); return "我是StaticClass1的静态方法的返回值"; } public StaticClass1() { System.out.println("我是StaticClass1的无参构造函数"); } public static void main(String[] args) { /* 日志输出: 我是StaticClass1的静态代码块 我是StaticClass1的静态方法 */ } }
StaticClass2类
package com.tyj.study.thinkinjava; /* * *@Description: *@Author:TYJ *@Date: create in 2019/7/9 17:22 */ public class StaticClass2 { { System.out.println("我是StaticClass2的普通代码块"); } private String nonstaticData = nonstaticMethod(); static String staticData = staticMethod(); static{ System.out.println("我是StaticClass2的静态代码块"); } private static String staticMethod(){ System.out.println("我是StaticClass2的静态方法"); return "我是StaticClass2的静态方法的返回值"; } private String nonstaticMethod(){ System.out.println("我是StaticClass2的非静态方法"); return "我是StaticClass2的非静态方法的返回值"; } public StaticClass2() { System.out.println("我是StaticClass2的无参构造函数"); } public static void main(String[] args) { /* 日志输出: 我是StaticClass2的静态方法 我是StaticClass2的静态代码块 */ } }
StaticClass3类
package com.tyj.study.thinkinjava; /* * *@Description: *@Author:TYJ *@Date: create in 2019/7/9 17:22 */ public class StaticClass3 { static String staticData = staticMethod(); { System.out.println("我是StaticClass3的普通代码块"); } static{ System.out.println("我是StaticClass3的静态代码块"); } public static String staticMethod(){ System.out.println("我是StaticClass3的静态方法"); return "我是StaticClass3的静态方法的返回值"; } public StaticClass3() { System.out.println("我是StaticClass3的无参构造函数"); } public static void main(String[] args) { StaticClass2 staticClass = new StaticClass2(); /* 日志输出: 我是StaticClass3的静态方法 我是StaticClass3的静态代码块 我是StaticClass2的静态方法 我是StaticClass2的静态代码块 我是StaticClass2的普通代码块 我是StaticClass2的非静态方法 我是StaticClass2的无参构造函数 */ } }
StaticClass4类
package com.tyj.study.thinkinjava; /* * *@Description: *@Author:TYJ *@Date: create in 2019/7/9 17:22 */ public class StaticClass4 { { System.out.println("我是StaticClass4的普通代码块"); } static{ System.out.println("我是StaticClass4的静态代码块"); } static String staticData = staticMethod(); private static String staticMethod(){ System.out.println("我是StaticClass4的静态方法"); return "我是StaticClass4的静态方法的返回值"; } public StaticClass4() { System.out.println("我是StaticClass4的无参构造函数"); } public static void main(String[] args) { StaticClass3.staticMethod(); /* 日志输出: 我是StaticClass4的静态代码块 我是StaticClass4的静态方法 我是StaticClass3的静态方法 我是StaticClass3的静态代码块 我是StaticClass3的静态方法 */ } }
StaticClass5类
package com.tyj.study.thinkinjava; /* * *@Description: *@Author:TYJ *@Date: create in 2019/7/9 17:22 */ public class StaticClass5 { { System.out.println("我是StaticClass5的普通代码块"); } static{ System.out.println("我是StaticClass5的静态代码块"); } static String staticData = staticMethod(); private static String staticMethod(){ System.out.println("我是StaticClass5的静态方法"); return "我是StaticClass5的静态方法的返回值"; } public StaticClass5() { System.out.println("我是StaticClass5的无参构造函数"); } public static void main(String[] args) { StaticClass5 a = new StaticClass5(); StaticClass5 b = new StaticClass5(); /* 日志输出: 我是StaticClass5的静态代码块 我是StaticClass5的静态方法 我是StaticClass5的普通代码块 我是StaticClass5的无参构造函数 我是StaticClass5的普通代码块 我是StaticClass5的无参构造函数 */ } }
分析:
1-分析StaticClass1,可以发现只要调用类的静态方法(即main方法),类的静态方法和静态变量都会被加载,即执行一次;
2-分析StaticClass1和StaticClass2,可发现类的静态方法和静态变量调用顺序只和其在类中的代码顺序有关,即谁在前,先执行谁;
3-分析StaticClass3,当调用StaticClass3的main方法时,会先初始化StaticClass3的静态方法和静态代码块,在执行main方法内的代码;
4-继续分析StaticClass3;执行main方法内的StaticClass2 staticClass = new StaticClass2()时,会依次初始化StaticClass2的静态方法和静态变量,非静态变量和普通代码块,构造函数;
5-分析StaticClass4;当调用StaticClass4的main方法时,会先初始化StaticClass4的静态方法和静态代码块;然后执行StaticClass3.staticMethod(),这里直接调用StaticClass3的静态方法(没有实例一个StaticClass3对象),StaticClass3的静态变量和静态代码块也被初始化了;
6-分析StaticClass5;发现连续创建两个StaticClass5类时,普通代码块和构造函数会被加载两次,但静态代码块和静态变量,只会加载一次
总结:
1-当创建一个对象,或者执行类的静态方法时,类的静态变量和静态代码块,都会被先加载一次;
2-多次创建对象或执行类的静态方法时,类的静态变量和静态代码块只会在第一次被加载,后面不会被重复加载;
3-当创建一个对象时,会依次加载:
-
- 类的静态代码块和静态变量(两者按代码顺序加载,且两者只会被加载一次,不会重复加载);
- 类的非静态变量和普通代码块(每创建一个对象,非静态变量和普通代码块就会被加载一次,两者顺序是按代码顺序加载);
- 类的构造函数(每创建一个对象,构造函数就会被加载一次);