淺談反射

反射機制做用

  1. 在運行時分析類的能力
  2. 在運行時查看對象
  3. 實現通用的數組操做代碼

反射機制的實現

採用Class類和java.lang.reflect 類庫一塊兒實現 <反射>機制java

  1. Class 類: 表明一個目標類。
  2. Field 類: 表明目標類的成員變量。
  3. Method 類: 表明目標類的方法。
  4. Constructor 類: 表明目標類的構造方法。
  5. Array 類: 提供了動態建立數組,以及訪問數組的元素的靜態方法。

Class 類

​ 在程序運行期間,Java運行時系統始終爲全部的對象維護一個被稱爲運行時的類型表示。這個信息跟蹤着每一個對象所屬的類。虛擬機利用運行時類型信息選擇相應的方法執行。segmentfault

​ 然而,能夠經過專門的Java類訪問這些信息。保存這些信息的類被成爲Class,這個名字很容易讓人混淆。Object 類中的getClass() 方法將返回一個Class類型的實例。數組

獲取Class對象的三種方法dom

  • 若是類在一個包裏,包的名字也做爲作類名的一部分。
Random generator = new Random();
Class cl = generator.getClass();
System.out.println(cl.getName());//java.util.Random
複製代碼
  • 若是類名保存字符串中,並可在運行時該變,便可使用這種方法。forName() 方法會爆ClassNotFoundException 異常,因此須要進行異常處理。函數

    Class.forName() 內部經過反射API根據目標類名將類手動加載到內存中,稱爲類加載器加載方法。加載過程當中會把目標類的static方法,變量,代碼塊加載到JVM,注意此時還沒有建立對象實例測試

String className = "java.util.Random";
 Class cl = class.forName(className);
複製代碼
  • 若是T是任意的Java類型(或void 關鍵字),T.class 將表明匹配的類對象
Class cl = Random.class;
複製代碼

獲取構造器--Constructor 類

  • Constructor[] getConstructors():得到全部public構造器;
  • Constructor[] getDeclaredConstructors():得到全部訪問權限的構造器
  • Constructor getConstructor(Class[] params):根據指定參數得到對應構造器;
  • Constructor getDeclaredConstructor(Class[] params):根據指定參數得到對應構造器;

得到方法--Method 類

  • Method[] getMethods():得到全部public方法;
  • Method[] getDeclaredMethods():得到全部訪問權限的方法;
  • Method getMethod(String name, Class[] params):根據方法簽名獲取類自身對應public方法,或者從基類繼承和接口實現的對應public方法
  • Method getDeclaredMethod(String name, Class[] params):根據方法簽名得到對應的類自身聲明方法訪問權限不限

得到變量--Field 類

  • Field[] getFields():得到類中全部public變量
  • Field[] getDeclaredFields():得到類中全部訪問權限變量
  • Field getField(String name):根據變量名獲得對應的public變量
  • Field getDeclaredField(String name):根據變量名得到對應的變量,訪問權限不限

實戰

咱們來個例子加深一下印象。spa

打印一個類的全部構造函數

public static void printConstructors(Class cl) {
       //返回包含Constructor 對象的數組,其中包含了Class對象的全部構造器
       Constructor[] constructors = cl.getDeclaredConstructors();

       for (Constructor c: constructors) {
           //String getName()
           //返回一個用於描述構造器、方法或域名的字符串
           String name = c.getName();
           System.out.print(" ");
           String modifiers = Modifier.toString(c.getModifiers());
           if (modifiers.length()>0)
               System.out.print(modifiers+ " ");
           System.out.print(name+"(");
           //Class[] getParameterTypes() (在Constructor 和 Method 類中)
           //返回一個用於描述參數類型的Class對象數組
           printParameterType(c.getParameterTypes());
           System.out.println(");");
       }
   }
複製代碼

打印一個類的全部方法

public static void printMethods(Class cl) {
       //返回包含Method 對象的數組,返回這個類或接口的所有方法,但不包括由超類繼承了的方法
       Method[] methods = cl.getDeclaredMethods();
       for (Method m:methods) {
           //Class getReturnType() (在 Method 類中)
           //返回一個用於描述返回類型的Class對象
           Class retType = m.getReturnType();
           String name = m.getName();

           System.out.print(" ");
           //打印修飾符、返回類型和方法名稱
           String modifiers =Modifier.toString(m.getModifiers());
           if (modifiers.length()>0)
               System.out.print(modifiers+" ");
           System.out.print(retType.getName()+" "+ name + "(");

           printParameterType(m.getParameterTypes());
           System.out.println(");");
       }
   }
複製代碼

打印一個類的全部字段

public static void printFields(Class cl) {
       //Field[] getDeclaredFields()
       //返回包含Field 對象的數組,這些對象記錄了這個類的所有域
       Field[] fields = cl.getDeclaredFields();

       for (Field f : fields){
           Class type = f.getType();
           String name = f.getName();
           System.out.print(" ");
           String modifiers = Modifier.toString(f.getModifiers());
           if (modifiers.length()>0)
               System.out.print(modifiers+" ");
           System.out.println(type.getName()+" "+ name+ ";");
       }
   }
複製代碼

打印方法的參數類型

public static void printParameterType(Class[] paramTypes) {
       for (int j = 0;j<paramTypes.length;j++) {
           if (j>0)
               System.out.print(", ");
           System.out.print(paramTypes[j].getName());
       }
   }
複製代碼

測試

public static void main(String[] args) {
       String name;
       if (args.length>0)
           name = args[0];
       else {
           Scanner in = new Scanner(System.in);
           System.out.println("Enter class name(e.g java.util.Date): ");
           name = in.next();
       }
       try {
           //print class name and superclass name (if != object)
           //調用Class 的靜態方法 forName 得到類名對應的Class 對象
           Class cl = Class.forName(name);
           //獲取父類所對應的Class 對象
           Class supercl = cl.getSuperclass();
           //返回對應modifiers 中位設置的修飾符的字符串表示
           String modifiers = Modifier.toString(cl.getModifiers());

           if (modifiers.length()>0)
               System.out.print(modifiers+" ");
           System.out.print("class "+ name);
           //判斷是否有繼承父類
           if (supercl != null  && supercl != Object.class)
               System.out.print(" extends "+ supercl.getName());

           System.out.print("\n{\n");
           printConstructors(cl);
           System.out.println();
           printMethods(cl);
           System.out.println();
           printFields(cl);
           System.out.println("}");


       }catch (ClassNotFoundException ex) {
           ex.printStackTrace();
       }
       System.exit(0);
   }
複製代碼

參考

JAVA核心技術(卷1)原書第10版code

反射筆記對象

相關文章
相關標籤/搜索