<script type="text/javascript"></script>
看了王森的《JAVA深度歷險》,做了一個簡單的學習筆記。
1. JAVA類裝載器在裝載類的時候是按需加載的,只有當一個類要使用(使用new 關鍵字來實例化一個類)的時候,類加載器纔會加載這 個類並初始化。
類Main:
- public class Main {
- public static void main(String[] args) {
- A a = new A();
- a.print();
- B b = new B();
- b.print();
- }
- }
類A:
- public class A {
- public void print() {
- System.out.println("Using Class A");
- }
- }
類B:
- public class B {
- public void print() {
- System.out.println("Using Class B");
- }
- }
執行:java -varbose:class Main
執行結果:
E:/DEV>java -verbose:class Main
[Opened C:/Program Files/Java/jre1.5.0_11/lib/rt.jar] (類裝載器會首先加載rt.jar加載基礎類)
.
.
[Loaded Main from file:/E:/DEV/] (類裝載器載入相應類並初始化)
[Loaded A from file:/E:/DEV/]
Using Class A
[Loaded B from file:/E:/DEV/]
Using Class B
2. 讓JAVA程序具有動態性
使用顯式方式來實現動態性,我們需要自己動手處理類載入時的細節部分。
兩種方法:
|
+-- 隱式的 : 使用new關鍵字讓類加載器按需求載入所需的類
|
+-- 顯式的 :
|
+-- 由 java.lang.Class的forName()方法加載
|
+-- 由 java.lang.ClassLoader的loadClass()方法加載
(1) 使用Class.forName()
Class.forName()方法具有兩個重載的方法:
+- public static Class forName(String className)
|
+- public static Class forName(String className, boolean initialize,ClassLoader loader)
參數說明:
className - 所需類的完全限定名
initialize - 是否必須初始化類(靜態代碼塊的初始化)
loader - 用於加載類的類加載器
調用只有一個參數的forName()方法等效於 Class.forName(className, true, loader)。
這兩個方法,最後都要連接到原生方法forName0(),其定義如下:
private static native Class forName0(String name, boolean initialize,ClassLoader loader) throws ClassNotFoundException;
只有一個參數的forName()方法,最後調用的是:
forName0(className, true, ClassLoader.getCallerClassLoader());
而三個參數的forName(),最後調用的是:
forName0(name, initialize, loader);
所以,不管使用的是new 來實例化某個類、或是使用只有一個參數的Class.forName()方法,內部都隱含了“載入類 + 運行靜態代碼塊”的步驟。而使用具有三個參數的Class.forName()方法時,如果第二個參數爲false,那麼類加載器只會加載類,而不會初始化靜態代碼塊,只有當實例化這個類的時候,靜態代碼塊纔會被初始化,靜態代碼塊是在類第一次實例化的時候才初始化的。
(2) 直接使用類加載器
+— 獲得對象所屬的類 : getClass()方法
|
+— 獲得該類的類加載器 : getClassLoader()方法
- public class Main3 {
- public static void main(String[] args) throws Exception {
- Main3 main3 = new Main3();
- System.out.println("準備載入類");
- ClassLoader loader = main3.getClass().getClassLoader();
- Class clazzA = loader.loadClass(args[0]);
- System.out.println("實例化類A");
- A o1 = (A) clazzA.newInstance();
- }
- }