類的加載過程
類的加載過程
類的主動使用和被動使用
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函數計算出來的,過於複雜,無法在類的加載,連接階段進行計算出來,所以要進行初始化