1. 程式人生 > 其它 >Java反射-1

Java反射-1

1.基本概念

a.編譯器與執行期

  1. 編譯期:把原始碼交給編譯器編譯成計算機可以執行的檔案的過程(Java程式碼程式設計.class檔案的過程),只是做了一些翻譯功能。
  2. 執行期:將編譯後的檔案交給計算機執行直至程式執行結束。(在磁碟中的程式碼放到記憶體中執行起來)

b.Java反射機制概念及作用

  • Java反射機制: 動態獲取資訊以及動態呼叫物件方法的功能。在執行狀態中,對於任意一個類,都能知道這個類的所有屬性以及方法;對於任意一個物件,都能夠呼叫它的任意方法和屬性。

  • Java反射機制在伺服器程式和中介軟體程式中應用廣泛(伺服器端根據客戶請求動態呼叫某個物件的特定方法)。

c.Java反射機制提供的主要功能

  1. 執行時判斷任意一個物件所屬的類。
  2. 執行時構造任意一個類的物件。
  3. 執行時判斷任意一個類所具有的成員變數和方法。
  4. 執行時呼叫任意一個物件的方法。
  5. 生成動態代理。(關於動態代理見 https://www.jianshu.com/p/9bcac608c714)

下表:反射可訪問的常用資訊

d.Java反射機制的優缺點

優點
  1. 能夠執行時動態獲取類的例項,大大提高系統的靈活性和擴充套件性
  2. 與Java動態編譯相結合,可以實現無比強大的功能
  3. 對於Java這種先編譯後執行的而語言,能讓我們很方便的建立靈活的程式碼。這些程式碼可以在執行時裝配,無需在元件之間進行原始碼的連線,更加容易實現面向物件。
缺點
  1. 反射會消耗一定的系統資源(不需動態建立物件時不必使用反射)
  2. 反射呼叫方法時可以忽略許可權檢查獲取類的私有方法和屬性,可能會破環類的封裝性導致安全問題。

2.Java反射機制API

java.lang.Class類(實現反射的關鍵所在)

  • Class類的一個例項表示Java的一種資料型別(類、介面、列舉、註解、陣列、基本資料型別、void)。Class無公有構造方法,Class例項是由JVM在類載入時自動建立的。

獲取Class例項的方法

  1. 每一種型別(類、介面)都有一個class靜態變數可以獲得Class例項
    Class clz1 = String.class;
  2. 每一個物件都有getClass()方法獲得Class例項(Object類提供的例項方法)
    String str = "Hello"; Class clz2 = str.getClass();

java.lang.reflect包

  • 該包提供了反射用到的類,主要類說明如下:
  1. Constructor類:提供類的構造方法資訊
  2. Field類:提供類或介面中成員變數資訊
  3. Method類:提供類或介面成員方法資訊
  4. Array類:提供了動態建立和訪問Java陣列的方法
  5. Modifier類:提供類和成員訪問修飾符資訊

程式碼例項(forName(String))建立某個類的執行時物件,若無則丟擲ClassNotFoundException異常

        //動態載入String類的執行時物件
        Class c = Class.forName("java.lang.Integer");
        //獲取成員方法集合
        Method[] methods = c.getDeclaredMethods();
        //遍歷成員方法集合
        for(Method method: methods){
            //列印修飾符
            System.out.println(Modifier.toString(method.getModifiers()));
            //列印返回值型別名
            System.out.println(method.getReturnType().getName() + " ");
            //列印方法名
            System.out.println(method.getName() + " ");
            System.out.println();

3.Java通過反射訪問構造方法

  • 為動態獲取物件構造方法的資訊,首先需建立一個Constructor型別的物件或陣列via下列方法之一
  1. getConstructors()
  2. getConstructors(Class<?>...parameterTypes)
  3. getDeclaredConstructors()
  4. getDeclaredConstructor(Class<?>...parameterTypes)

注:若訪問指定的構造方法,需根據該構造方法的入口引數的型別來訪問。
eg訪問一入口引數為int和String型別的構造方法
objectClass.getDeclaredConstructor(int.class, String.class)

建立的Constructor物件標識一個構造方法,然年後利用Constructor物件的方法操作構造方法。常用方法如下:

對於getModifiers()方法,通過java.lang.reflect.Modifier類可以解析出該方法的返回值所表示的修飾符資訊。
在該類中提供了一系列用來解析的靜態方法,既可以檢視是否被指定的修飾符修飾,還可以字串形式獲得所修飾符。

4.Java通過反射執行方法(獲取方法)

  • 要動態獲取一個物件方法的資訊,需通過下列方法之一建立一個Method型別的物件或陣列。
  1. getMethods()
  2. getMethods(String name,Class<?>...parameterTypes)
  3. getDeclaredMethods()
  4. getDeclaredMethods(String name,Class<?>...parameterTypes)

Method類常用方法如下

注:invoke需先指定物件obj eg.
test1 a = new test1("Mike", 22);
Object obj = method.invoke(a, "baby", "I");

5.Java通過反射訪問成員變數

  • 通過下列方法訪問成員變數時將返回Field型別的物件或陣列
  1. getFields()
  2. getField(String name)
  3. getDeclaredFields()
  4. getDeclaredField(String name)

Field類常用方法如下: