目錄
- 1. 類的加載時機
- 2. 類的初始化
- 會發生類的初始化的情況:
- 不會發生類的初始化的情況:
1. 類的加載時機
以下5個情況,只要有1個出現,那么類的加載器就會將這個類的class檔案加載到記憶體中:
- 創建類的實體,
- 使用類的靜態變數或靜態方法,
- 使用反射方式來強制創建某個類或介面對應的java.lang.Class物件,
- 初始化某個類的子類,
- 直接使用java.exe命令來運行某個主類,
2. 類的初始化
類的初始化主要就是對靜態的類變數進行初始化:
(1)執行類構造器
(2)當初始化一個類的時候,如果發現其父類還沒有進行初始化,則需要先觸發其父類的初始化
(3)虛擬機會保證一個類的
雖然類的加載大多數時候和類初始化是一氣呵成的,但其實類的加載不一定就會觸發類的初始化,
會發生類的初始化的情況:
(1)當虛擬機啟動,先初始化main方法所在的類
(2)使用new關鍵字創建一個類的物件
(3)呼叫該類的靜態變數(final的常量除外)和靜態方法
(4)使用java.lang.reflect包的方法對類進行反射呼叫
(5)當初始化一個類時,如果其父類沒有被初始化,則先會初始化他的父類
不會發生類的初始化的情況:
(1)參考靜態常量不會觸發此類的初始化(常量在鏈接階段就存入呼叫類的常量池中了)
(2)當訪問一個靜態成員時,只有真正宣告這個靜態成員的類才會被初始化,當通過子類參考父類的靜態變數,不會導致子類初始化
(3)某型別陣列的動態初始化,不會觸發此類的初始化
代碼示例:
(1)參考靜態常量不會觸發此類的初始化,靜態代碼塊不會執行,去掉final會執行
public class ClinitTest {
public static void main(String[] args) {
System.out.println(Son.NUM);
System.out.println(Father.NUM);
}
}
class Father {
public static final int NUM = 10;
static {
System.out.println("Father類靜態代碼塊");
}
}
class Son extends Father {
static {
System.out.println("Son類靜態代碼塊");
}
}
(2)當訪問一個靜態成員時,只有真正宣告這個靜態成員的類才會被初始化,下面代碼中Son類不會初始化,Son類的靜態代碼塊不會執行
public class ClinitTest {
public static void main(String[] args) {
System.out.println(Son.NUM);
}
}
class Father {
public static int NUM = 10;
static {
System.out.println("Father類靜態代碼塊");
}
}
class Son extends Father {
static {
System.out.println("Son類靜態代碼塊");
}
}
(3)某型別陣列的動態初始化,不會觸發此類的初始化
public class ClinitTest {
public static void main(String[] args) {
//沒有創建Person類的物件,創建的是準備用來裝Person物件的陣列物件
Person[] people = new Person[10];
}
}
class Person {
static {
System.out.println("Person類靜態代碼塊");
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/47224.html
標籤:Java
上一篇:李胖胖的第一天學習linux
下一篇:創建并啟動執行緒
