1. 程式人生 > >Java反射機制的引入、使用和優缺點

Java反射機制的引入、使用和優缺點

  • 反射的引入

  1. Java編碼時知道類和物件的具體資訊,此時直接對類和物件進行操作即可,無需反射
  2. 如果編碼時不知道類或者物件的具體資訊,此時應該使用反射來實現
            比如類的名稱放在XML檔案中,屬性和屬性值放在XML檔案中,需要在執行時讀取XML檔案,動態獲取類的資訊
            在編譯時根本無法知道該物件或類可能屬於哪些類,程式只依靠執行時資訊來發現該物件和類的真實資訊
        反射的作用:建立物件、操作屬性、呼叫方法

        在JDK中,主要由以下四個類來實現Java反射機制,這些類都位於java.lang.reflct包中

                Class類:代表一個類,是Java反射機制的起源和入口
                    用於獲取與類相關的各種資訊
                    提供了獲取類資訊的相關方法

                    Class類繼承自Object類

                Class類是所有類的共同的圖紙
                    每個類有自己的物件,同時每個類也看做是一個物件,有共同的圖紙Class,存放類的結構資訊,能夠通過相應方法取出相應的資訊:類的名字、屬性、方法、構造方法、父類和介面

Class類常用方法

 

獲取類的Class資訊

  • 使用反射技術

            動態建立物件
                方法1:通過Class的newInstance()方法
                    該方法要求該Class物件的對應類有無參構造方法
                    執行newInstance()實際上就是執行無參構造方法來建立該類的例項
Class clazz=Class.forName("com.bjsxt.reflection.Student");
Object obj=clazz.newInstance();
//相當於執行語句:
Student stu = new Student();
                方法2:通過Constructor的newInstance()方法
                     先使用Class物件獲取指定的Constructor物件
                    再呼叫Constructor物件的newInstance()建立Class物件對應類的物件
                    通過該方法可選擇使用指定構造方法來建立物件
Class clazz = Class.forName("com.bjsxt.reflection.Student");
Constructor cons = clazz.getConstructor(String.class,
int.class, float.class );
Object obj = cons.newInstance( "lkl", 32, 56.5f );
//相當於執行語句:
Student stu=new Student("lkl",32,56.5f);

obj = clazz.getConstructor().newInstance();
//相當於執行語句:
Student stu = new Student();
            動態修改查詢屬性值

                通過Class物件的getFields()或者getField()方法可以獲得該類所包括的全部Field屬性或指定Field屬性。Field類提供了以下方法來訪問屬性

Class clazz = Class.forName("com.bjsxt.reflection.Student");
Object obj = clazz.newInstance();
// 呼叫getDeclaredField("name")方法取得name屬性對應的Field物件,可以類獲取私有屬性
Field f = clazz.getDeclaredField("name");
// 取消屬性的訪問許可權控制,即使private屬性也可以進行訪問。
f.setAccessible(true);
// 呼叫get()方法取得對應屬性值。
System.out.println(f.get(obj));
// 呼叫set()方法給對應屬性賦值。
f.set(obj, "lkl");
// 呼叫get()方法取得對應屬性修改後的值。
System.out.println(f.get(obj));
            動態執行方法
                通過Class物件的getMethods()方法可以獲得該類所包括的全部方法,返回值是Method[]
                通過Class物件的getMethod()方法可以獲得該類所包括的指定方法,返回值是Method
                每個Method物件對應一個方法,獲得Method物件後,可以呼叫其invoke()來呼叫對應方法
 // 建立該類的一個物件
Class clazz = InvokeMethod.class;
Object obj = clazz.newInstance();
// 呼叫該物件的add方法
Method amethod = clazz.getMethod("add", new Class[] { int.class,int.class });
Object result = amethod.invoke(obj, new Object[] { 5, 7 });
System.out.println(result);
// 呼叫該物件的shout方法
Method smethod = clazz.getMethod("shout", new Class[] { String.class });
smethod.invoke(obj, new Object[] { "lkl" });
//相當於如下語句
InvokeMethod im=new InvokeMethod();
int sum=im.add(5, 7);
System.out.println(sum);
im.shout("lkl");
  • 反射技術優缺點

  • 優點
  1. 反射提高了Java程式的靈活性和擴充套件性,降低耦合性,提高自適應能力。它允許程式建立和控制任何類的物件,無需提高硬編碼目標類
  2. 反射是其他一些常用語言,如C、C++、Fortran或者Pascal等不具備的
  3. Java反射技術應用領域很廣,如軟體測試、JavaBean等
  4. 許多流行的開源框架例如Struts、Hibernate、Spring在實現過程中都採用了該技術
  • 缺點
  1. 效能問題:使用反射基本上是一種解釋操作哦,用於欄位和方法接入時要遠慢於直接程式碼。因此Java反射機制只要應用在對;靈活性和擴充套件性要求很高的系統框架上,普通程式不建議使用
  2. 使用反射會模糊程式內部邏輯:程式設計師希望在程式碼中看到程式的邏輯,反射等繞過了原始碼的技術,因而會帶來維護問題。反射程式碼比相應的直接程式碼更復雜