Java反射學習總結(二)

使用 Class.forName() 加載類

在一些應用中,我們無法事先知道使用者將會加載什麼類,而必須讓使用者指定類名類加載類,我們就可以用Class的靜態forName()方法來實現動態加載類,如下:

package CoreJava.day_2;

/**
 * @author 李智
 * @date 2016/12/4
 */
public class ForNameDemo {
    public static void main(String[] args) {
        try {
            Class c = Class.forName(args[0]);
            System.out.println("類名:" +
                    c.getName());
            System.out.println("是否爲接口:" +
                    c.isInterface());
            System.out.println("是否爲基本類型:" +
                    c.isPrimitive());
            System.out.println("是否爲數組:" + c.isArray());
            System.out.println("父類名:" +
                    c.getSuperclass().getName());
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("沒有指定的類名");
        } catch (ClassNotFoundException e) {
            System.out.println("找不到指定類");
        }
    }
}

輸出:

java ForNameDemo java.util.String
類名:java.util.Scanner
是否爲接口:false
是否爲基本類型:false
是否爲數組:false
父類名:java.lang.Object

Class的靜態方法forName()方法有兩個版本,上面所示的是指定類名版本,還一個版本可以讓我們指定類名,加載時是否執行靜態代碼塊,指定類的加載器(Class loader):

static Class forName(String name, boolean initialize, ClassLoader loader)


上一篇
寫到過,假設在加載類的時候,如果類中有定義靜態代碼塊則會執行它,我們可以使用forName的第二個版本,將initialize設爲false,如果在加載類時並不會馬上執行靜態代碼塊的代碼,而會在使用類實例對象時才執行靜態代碼塊,我們可以做一下測試:

package CoreJava.day_2;

/**
 * @author 李智
 * @date 2016/12/4
 */
public class TestClass2 {
        static {
            System.out.println("[執行靜態代碼塊]");
        }
}

在這裏我們只定義了靜態代碼塊顯示一段信息,來觀察靜態代碼塊何時被執行。先用第一個版本來測試:

package CoreJava.day_2;

/**
 * @author 李智
 * @date 2016/12/4
 */
public class ForNameDemoV1 {
    public static void main(String[] args) {
        try {
            System.out.println("加載TestClass2");
            Class c = Class.forName("TestClass2");

            System.out.println("TestClass2聲明");
            TestClass2 test = null;

            System.out.println("TestClass2實例對象");
            test = new TestClass2();
        } catch (ClassNotFoundException e) {
            System.out.println("找不到指定的類");
        }
    }
}

輸出:

加載TestClass2
[執行靜態代碼塊]
TestClass2聲明
TestClass2實例對象

Process finished with exit code 0

可以從結果看出,第一個版本的forName()方法在加載類之後,會馬上執行靜態代碼塊,再看看第二種結果怎麼樣:

package CoreJava.day_2;

/**
 * @author 李智
 * @date 2016/12/4
 */
public class ForNameDemoV2 {
    public static void main(String[] args) {
        try {
            System.out.println("加載TestClass2");
            Class c = Class.forName(
                    "CoreJava.day_2.TestClass2",
                    false, // 加載類時不執行靜態代碼塊代碼
                    Thread.currentThread().getContextClassLoader());

            System.out.println("TestClass2聲明");
            TestClass2 test = null;

            System.out.println("TestClass2實例對象");
            test = new TestClass2();
        } catch (ClassNotFoundException e) {
            System.out.println("找不到指定的類");
        }
    }
}

輸出:

加載TestClass2
TestClass2聲明
TestClass2實例對象
[執行靜態代碼塊]

Process finished with exit code 0

由於在第二個版本的forName()方法中,把initialize設爲了false,所以加載類時並不會馬上執行靜態代碼塊,而會在類實例對象時纔去執行靜態代碼塊代碼,第二個版本的forName()方法需要一個類加載器(Class loader)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章