運行以下代碼的Test1與Test2分別輸出什麼結果java
public class Parent { static { System.out.println("Parent static invoke"); } public static final String FINAL_STR="FINAL_STR"; public static final Test FINAL_OBJECT=new Test(); public Parent(){ System.out.println("Parent init"); } } public class Child extends Parent { static { System.out.println("Child static invoke"); } public Child(){ System.out.println("child init"); } } public class Test { public static void main(String[] args) { System.out.println(Child.FINAL_STR); } } public class Test2 { public static void main(String[] args) { System.out.println(Child.FINAL_OBJECT); } }
FINAL_STR
Parent static invoke cn.lonecloud.Test@5e2de80c
FINAL_STR
爲final而且爲static
變量,其在調用static final
變量的時候不會觸發類的初始化操做。因此結果如上Test1
字節碼:Compiled from "Test.java" public class cn.lonecloud.Test { public cn.lonecloud.Test(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #4 // String FINAL_STR 5: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return }
ldc #4 // String FINAL_STR
其爲獲取靜態化變量方法,其爲將常量壓入棧中,因爲靜態變量在JVM中存在常量池的概念,會將字符串進行優化,因此並不會觸發類初始化Compiled from "Test.java" public class cn.lonecloud.Test { public cn.lonecloud.Test(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: getstatic #3 // Field cn/lonecloud/Child.FINAL_OBJECT:Lcn/lonecloud/Test; 6: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 9: return }
因爲須要使用到Child類的父類中的
FINAL_OBJECT
變量,未使用到Child
類中的變量,因此不會對Child類進行初始化,初始化的爲其父類。jvm
經過添加JVM參數
-XX:+TraceClassLoading
能夠查看類加載狀況優化
可見,會對Child,Parent類進行類加載操做,可是調用static方法,只有Parent類會調用static進行初始化操做。code
final static
進行修飾的時候,則不會對類進行初始化操做