類裝載順序
類加載過程
Class.forName()和ClassLoader.loadClass 對比
Class.forName(className)方法,内部實際調用的方法是Class.forName(className,true,classloader);
第2個boolean參數表示類是否需要初始化, Class.forName(className)預設是需要初始化。
一旦初始化,就會觸發目标對象的 static塊代碼執行,static參數也也會被再次初始化。
ClassLoader.loadClass(className)方法,内部實際調用的方法是 ClassLoader.loadClass(className,false);
第2個 boolean參數,表示目标對象是否進行連結,false表示不進行連結,由上面介紹可以,
舉個例子
實體類:
public class Person {
public Person() {
System.out.println("構造代碼塊");
}
static {
System.out.println("靜态代碼塊!!!");
}
//靜态變量
private static String staticFiled = staticMethod();
//指派靜态變量的靜态方法
public static String staticMethod(){
System.out.println("執行了靜态方法");
return "給靜态字段指派了";
}
public static String staticMethod2(){
System.out.println("執行了靜态方法 2222");
return "給靜态字段指派了222";
}
{
System.out.println("普通的代碼塊");
}
}
測試類:
public static void main(String[] args) {
String PersionClassName = "com.jacky.thread.classloader.Person";
System.out.println("==== Classloader =======");
ClassLoader loader = ClassLoader.getSystemClassLoader();
Class<?> personClassLoader;
try {
personClassLoader = loader.loadClass(PersionClassName);
System.out.println("person loadClass : " + personClassLoader.getName());
System.out.println("===== ClassForName ======");
Class personForName = Class.forName(PersionClassName);
System.out.println("person forName : " + personForName.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
輸出結果:
結果得出結論: ClassforName會對類初始化,也就是說會執行類中的靜态代碼塊,以及對靜态變量的指派等操作
總結
- 整個類加載階段分五步:加載、驗證、準備、解釋、初始化。
- ClassLoader :隻負責第一步加載,就是加載class到jvm記憶體中,沒有執行初始化操作
- Class.forName :會執行類中的靜态代碼塊,以及對靜态變量的指派等操作。