根據上一節的理論我們知道,每個類的接口被Java程序“首次主動使用”時才初始化,這一節我們就通過具體的實例來驗證一下
- 創建類的實例
public class MyTest1 {
public static void main(String[] args) {
new MyParent1();
}
}
class MyParent1 {
public static String str = "hello world";
static {
System.out.println("MyParent static block");
}
}
運行程序,輸出:
MyParent static block
類的靜態代碼塊被執行了,說明類進行了初始化
- 訪問某個類或接口的靜態變量,或者對該靜態變量賦值
public class MyTest1 {
public static void main(String[] args) {
System.out.println(MyParent1.str);
}
}
class MyParent1 {
public static String str = "hello world";
static {
System.out.println("MyParent static block");
}
}
運行程序,輸出:
MyParent static block
hello world
- 調用類的靜態方法
public class MyTest1 {
public static void main(String[] args) {
MyParent1.print();
}
}
class MyParent1 {
public static String str = "hello world";
public static void print(){
System.out.println(str);
}
static {
System.out.println("MyParent static block");
}
}
運行程序,輸出:
MyParent static block
hello world
- 反射
public class MyTest1 {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.shengsiyuan.jvm.classloader.MyParent1");
}
}
class MyParent1 {
public static String str = "hello world";
static {
System.out.println("MyParent static block");
}
}
運行程序,輸出:
MyParent static block
- 初始化一個類的子類
public class MyTest1 {
public static void main(String[] args) throws ClassNotFoundException {
new MyChild1();
}
}
class MyParent1 {
public static String str = "hello world";
static {
System.out.println("MyParent static block");
}
}
class MyChild1 extends MyParent1 {
public static String str2 = "welcome";
static {
System.out.println("MyChild1 static block");
}
}
運行程序,輸出:
MyParent static block
MyChild1 static block
- Java虛擬機啟動時被表明為啟動類的類
public class MyTest1 {
static {
System.out.println("MyTest1 static block");
}
public static void main(String[] args) throws ClassNotFoundException {
}
}
運行程序,輸出:
MyTest1 static block
非主動使用注意點
以上實例都是對主動使用的驗證,我們來看一下下面這個程序
public class MyTest1 {
public static void main(String[] args) throws ClassNotFoundException {
System.out.println(MyChild1.str);
}
}
class MyParent1 {
public static String str = "hello world";
static {
System.out.println("MyParent static block");
}
}
class MyChild1 extends MyParent1 {
static {
System.out.println("MyChild1 static block");
}
}
運行程序,輸出:
MyParent static block
hello world
我們可以看到,MyChild1 static block
并沒有打印出來,這里我們調用MyChild1.str明明是對類的靜態變量的訪問,但是MyChild1卻沒有被初始化,所以這里要注意的一點就是:
對于靜態字段來說,只有直接定義了該字段的類才會被初始化
參考資料:
圣思園JVM課程