Java類的加載是由類加載器來完成的,過程以下:java
首先,加載是把硬盤、網絡、數據庫等的class文件中的二進制數據加載到內存的過程,而後會在Java虛擬機的運行時數據區的堆區建立一個Class對象,用來描述該類,再在方法區存放這些二進制數據,用來保存類對應的數據結構數據庫
Java的類加載器有哪些?bootstrap
下面的String對象是由bootstrap根類加載器加載的,而自定義類C是由系統加載器加載的:網絡
/** * 源文檔中這樣描述: * Some implementations may use null to represent the bootstrap class loader. * This method will return null in such implementations * if this class was loaded by the bootstrap class loader. * @author Administrator * */ public class ClassLoader2 { //測試 public static void main(String[] args) throws ClassNotFoundException { Class c1 = Class.forName("java.lang.String"); System.out.println("String類的加載器:"+c1.getClassLoader());//bootstrap根類加載器(C++實現的),返回null Class c2 = Class.forName("com.mlxs.classloader.MyClass"); System.out.println("自定義MyClass類的加載器:"+c2.getClassLoader());//AppClassLoader 系統(應用)加載器 /** * 返回數據: * String類的加載器:null * 自定義MyClass類的加載器:sun.misc.Launcher$AppClassLoader@425224ee */ } } class MyClass{ }
關於初始化,什麼狀況下初始化類?在主動使用的時候初始化:數據結構
一個例子:測試
public class ClassLoader1 { private static ClassLoader1 classLoader1 = new ClassLoader1(); private ClassLoader1(){ a ++; b ++; } public static int a; public static int b = 0; public static ClassLoader1 getIntsance(){ return classLoader1; } //測試 public static void main(String[] args) { ClassLoader1 clazz = ClassLoader1.getIntsance(); /** * 類加載後, * 準備階段:(1)classLoader1賦值null,(2)a和b都賦值默認值0; * 初始化階段: (1)new classLoader1的時候,a++(=1),b++(=1) * (2)a沒默認值,值不變;b默認值爲0,b賦值0 * 因此,最後a=1,b=0 * * 若是把new ClassLoader1()放到int a b 的後面,則最後a=1,b=1 */ System.out.println("a:"+clazz.a); System.out.println("b:"+clazz.b); } }
結果:this
a:1 b:0
要注意的是:spa
子類主動使用,會致使父類的初始化;而父類主動使用,不會使子類初始化。如,new Object() 不會致使它的子類(全部的Java類)都初始化code
而子類實現接口,當子類被初始化,不會致使接口初始化。只有當接口中的靜態變量被使用時纔會初始化對象