类的加载过程
类的加载过程
类的主动使用和被动使用
JVM虚拟机规范规定了,每个类或者接口被Java程序首次主动使用是才会对其进行初始化
JVM规范的6种主动使用类的场景
-
new关键字
-
访问类的静态变量,会导致类的初始化
-
访问类的静态方法,会导致类的初始化
-
对某个类进行反射操作,会导致类的初始化
package online.hengtian.ClassLoaderTest; public class SimpleClass { public static final int SIMPLEINT=10; static { System.out.println("哎呀,我被初始化了"); } public SimpleClass(){ System.out.println("我被初始化方法初始化了") } }
public class MainTest { public static void main(String[] args) throws ClassNotFoundException { Class.forName("online.hengtian.ClassLoaderTest.SimpleClass"); } } /*输出 哎呀,我被初始化了 */
-
初始化子类也会导致父类的初始化,且如果只调用父类方法中的静态变量不会导致子类方法的初始化,即使是从子类中去访问的,见如下示例
package online.hengtian.ClassLoaderTest; public class Parent { public static int y=10; static { System.out.println("我是父类,我被初始化了"); } }
package online.hengtian.ClassLoaderTest; public class Child extends Parent{ public static int x=10; static { System.out.println("我是子类,怎么说"); } }
package online.hengtian; import static org.junit.Assert.assertTrue; import online.hengtian.ClassLoaderTest.Child; import org.junit.Test; /** * Unit test for simple App. */ public class AppTest { /** * Rigorous Test :-) */ @Test public void Test01(){ System.out.println(Child.x); } /** 输出: 我是父类,我被初始化了 我是子类,怎么说 10 **/ @Test public void Test02(){ System.out.println(Child.y); } /** 输出: 我是父类,我被初始化了 10 **/ }
-
执行main函数所在的类
package online.hengtian.ClassLoaderTest; public class Child extends Parent{ public static int x=10; static { System.out.println("我是子类,怎么说"); } public static void main(String[] args){ System.out.println("hello,我是main函数,我现在啥也没干"); } } /** 我是父类,我被初始化了 我是子类,怎么说 hello,我是main函数,我现在啥也没干 **/
类的被动使用
除了上述的六种主动使用的情况,其余都称为被动使用,都不会导致类的加载和初始化
-
构造某个类的数组不会导致类的初始化
@Test public void Test03(){ SimpleClass[] simpleClasses=new SimpleClass[10]; System.out.println(simpleClasses.length); }
虽然这其中使用了new关键字,但是它并不能导致Simple类的初始化,因此它是被动使用,该操作在实际上只是在堆内存开辟了一段连续的地址空间即SimpleClass所占的字节*10
-
引用类的**静态常量(final修饰的静态变量)**不会导致类的初始化
package online.hengtian.ClassLoaderTest; import java.util.Random; public class GlobalConstants { static { System.out.println("The GlobalConstants被初始化了"); } public static final int RANDOM=new Random().nextInt(); }
@Test public void Test04(){ System.out.println(GlobalConstants.RANDOM); } /** The GlobalConstants被初始化了 1957807993 **/ GlobalConstans中RANDOM是用Random函数计算出来的,过于复杂,无法在类的加载,连接阶段进行计算出来,所以要进行初始化