1. 程式人生 > >java之反射Reflect

java之反射Reflect

1.Class類的使用

(1)java中普通的資料型別類和靜態的成員不屬於物件。

(2)類也是物件,是java.lang.Class類的例項物件。

(3)Class類本身是無法new自身的。因為可以從原始碼看到:

         Class類本身的構造方法是一個私有的構造方法,只有java虛擬機器可以來呼叫。

(4)Class類的使用程式碼: 

package function.reflect;

/**
 * Class類的使用
 *
 * @author kimtian
 */
public class ClassUsed {
    public static void main(String[] args) {
        //Student 物件的例項
        Student student1 = new Student();
        //Student這個類也是一個例項物件,是Class類的例項物件
        //任意一個類都是Class的例項物件,這個例項物件有三種表示方式

        //第一種表示方式-->任何一個類都有一個隱含的靜態成員變數class
        Class c1 = Student.class;
        System.out.println(c1);

        //第二種表達方式  已經知道該類的物件,通過getClass方法呼叫
        Class c2 = student1.getClass();
        //第三種表達方式
        Class c3 = null;
        try {
            c3 = Class.forName("function.reflect.Student");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println(c2 == c3);
        /**
         * c1,c2表示了Student類的類型別(ClassType)
         * 萬事萬物皆物件
         * 類也是物件,是Class類的例項物件
         * 這個物件我們稱為該類的類型別
         */
        // 不管c1 or c2 都代表了foo類的類型別,一個類只可能是Class類的一個例項物件
        System.out.println(c1 == c2);

        //我們完全可以通過類的類型別建立該類的例項物件。-->通過c1 or c2 or c3建立Student的例項
        Student student2 = null;
        try {
            //需要有無引數的構造方法,否則會報錯
            student2 = (Student) c1.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

class Student {
}

2.動態載入類

(1)從上面可以看到   Class.forName("類的全稱")    可以用來建立類的例項。

         c1.newInstance();不僅表示了類的類型別,還代表了動態載入類;

         編譯時刻載入類是靜態載入類、執行時刻載入類是動態載入類,我們在做一些通過功能方法的時候最好使用動態載入類。

(2)靜態載入類的實現:

         由於使用的靜態載入類,如果我們沒有Office類,那麼在編譯Office類的時候就會出錯。     

         如果有一個類似於Word、Excel這樣的類出錯,全部其他的功能都使用不了。

package function.reflect;

/**
 * 如果有一個出問題,全部其他的功能也都使用不了
 * 每次增加新功能,要修改基礎程式碼
 *
 * @author kimtian
 */
public class Office {
    public static void main(String[] args) {
        if ("Word".equals(args[0])) {
            //new建立物件是靜態載入類,在編譯時刻就需要載入所有可能使用到的類。
            //只想在執行哪個時候載入哪個,就要使用動態載入類
            Word word = new Word();
            word.start();
        }
        if ("Excel".equals(args[0])) {
            Excel excel = new Excel();
            excel.start();
        }
    }
}

(3)動態載入類的實現:

          使用動態載入類,如果要使用Excel,但是沒有Excel類,則只在執行的時候才會報錯。但不會影響其他的,如Word的使用。

          我們給定一個OfficeAble的通用介面,使Word、Excel等都實現該介面,可擴充套件性好,新增類似其他的功能時,只需要增加新的程式碼實現OfficeAble通用介面。不用重新修改編譯這個功能基礎類。

package function.reflect;

/**
 * 如果需要加其他OfficeAble的具體實現,也不需要重新修改編譯這個類
 *
 * @author kimtian
 */
public class OffiiceBetter {
    public static void main(String[] args) {
        try {
            //動態載入類,在執行時刻載入
            Class c = Class.forName(args[0]);

            //通過類型別,建立該類物件
            OfficeAble oa = (OfficeAble) c.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}