Java反射機制的引入、使用和優缺點
阿新 • • 發佈:2019-02-15
反射的引入
- Java編碼時知道類和物件的具體資訊,此時直接對類和物件進行操作即可,無需反射
- 如果編碼時不知道類或者物件的具體資訊,此時應該使用反射來實現
在編譯時根本無法知道該物件或類可能屬於哪些類,程式只依靠執行時資訊來發現該物件和類的真實資訊
反射的作用:建立物件、操作屬性、呼叫方法
在JDK中,主要由以下四個類來實現Java反射機制,這些類都位於java.lang.reflct包中
Class類:代表一個類,是Java反射機制的起源和入口用於獲取與類相關的各種資訊
提供了獲取類資訊的相關方法
Class類繼承自Object類
每個類有自己的物件,同時每個類也看做是一個物件,有共同的圖紙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");
反射技術優缺點
優點
- 反射提高了Java程式的靈活性和擴充套件性,降低耦合性,提高自適應能力。它允許程式建立和控制任何類的物件,無需提高硬編碼目標類
- 反射是其他一些常用語言,如C、C++、Fortran或者Pascal等不具備的
- Java反射技術應用領域很廣,如軟體測試、JavaBean等
- 許多流行的開源框架例如Struts、Hibernate、Spring在實現過程中都採用了該技術
缺點
- 效能問題:使用反射基本上是一種解釋操作哦,用於欄位和方法接入時要遠慢於直接程式碼。因此Java反射機制只要應用在對;靈活性和擴充套件性要求很高的系統框架上,普通程式不建議使用
- 使用反射會模糊程式內部邏輯:程式設計師希望在程式碼中看到程式的邏輯,反射等繞過了原始碼的技術,因而會帶來維護問題。反射程式碼比相應的直接程式碼更復雜