參考自:http://www.jianshu.com/p/53eb4e16d00e
參考自:
什麼是反射。
反射(Reflection)能夠讓運行於 JVM 中的程式檢測和修改運行時的行為。 Class 類
在程式運行期間,Java運行時系統始終為所有的對象維護一個被稱為運行時的類型標識。虛擬機器利用運行時資訊選擇相應的方法執行。可以通過專門的Java類訪問這些資訊,儲存這些資訊的類被稱為Class。
將Class類中的forName和newInstance配合使用,可以根據儲存在字串中的類名建立一個對象。
String s = "java.util.Date";Object m = Class.forName(s).newInstance();
為什麼需要反射。
通過反射,我們能夠 在運行時檢測對象的類型; 動態構造某個類的對象; 檢測類的屬性和方法; 任意調用對象的方法; 修改建構函式、方法、屬性的可見度。 JUnit
JUnit通過反射來遍曆包含 @Test 註解的方法,並在運行單元測試時調用它們。 Web架構
開發人員可以在設定檔中定義對各種介面和類的實現。通過反射機制,架構能夠快速地動態初始化所需要的類。
Spring架構使用如下的設定檔:
<bean id="someID" class="com.programcreek.Foo"> <property name="someField" value="someValue" /></bean>
當Spring容器處理 bean 元素時,會使用Class.forName("com.programcreek.Foo")來初始化這個類,並再次使用反射擷取 property 元素對應的setter方法,為對象的屬性賦值。 Servlet
<servlet> <servlet-name>someServlet</servlet-name> <servlet-class>com.programcreek.WhyReflectionServlet</servlet-class><servlet>
如何使用反射。
反射的基本方法
本著不重複造輪子的原則,API 詳細參考自 這裡,下面只做簡單介紹。
在java.lang.reflect包中有三個重要的類: Field:描述類的域 Method:描述類的方法 Constructor:描述類的構造器
對於public域(包括超類成員): getFields getMethods getConstructors
對於其它域(包括私人和受保護的成員,不包括超類成員): gettDeclaredFields gettDeclaredMethods gettDeclaredConstructors
下面介紹 Java 反射的使用,其中 Person 類及測試完整代碼在本文最後。 載入類
// 載入類的3種方法 Class clazz = Class.forName("com.yano.reflect.Person"); Class clazz1 = new Person().getClass(); Class class2 = Person.class;
擷取類的無參建構函式,並執行個體化類
Class clazz = Class.forName("com.yano.reflect.Person"); Constructor c = clazz.getConstructor(null); Person p = (Person) c.newInstance(null);
擷取類的含參私人建構函式,並執行個體化類
Class clazz = Class.forName("com.yano.reflect.Person"); Constructor c = clazz .getDeclaredConstructor(new Class[] { String.class }); // 由於建構函式是 private 的,所以需要屏蔽Java語言的訪問檢查 c.setAccessible(true); Person p = (Person) c .newInstance(new Object[] { "I'm a reflect name!" });
擷取並調用類的無參方法
Class clazz = Class.forName("com.yano.reflect.Person"); Constructor c = clazz.getConstructor(null); Person p = (Person) c.newInstance(null); Method method = clazz.getMethod("fun", null); method.invoke(p, null);
擷取並調用類的含參方法
Class clazz = Class.forName("com.yano.reflect.Person"); Constructor c = clazz.getConstructor(null); Person p = (Person) c.newInstance(null); Method method = clazz.getMethod("fun", new Class[] { String.class }); method.invoke(p, new Object[] { "I'm a reflect method!" });
擷取類的欄位
Class clazz = Class.forName("com.yano.reflect.Person"); Constructor c = clazz .getDeclaredConstructor(new Class[] { String.class }); // 由於建構函式是 private 的,所以需要擷取控制許可權 c.setAccessible(true); Person p = (Person) c .newInstance(new Object[] { "I'm a reflect name!" }); Field f = clazz.getField("name"); Object value = f.get(p); Class type = f.getType(); System.out.println(type); if (type.equals(String.class)) { System.out.println((String) value); }
完整代碼
Person 類
package com.yano.reflect;public class Person { public String name = "default name"; public int[] array = new int[10]; public Person() { System.out.println(name); for (int i = 0; i < array.length; i++) { array[i] = i; } } private Person(String name) { this.name = name; System.out.println(name); } public void fun() { System.out.println("fun"); } public void fun(String name) { System.out.println(name); }}
test 類
package com.yano.reflect;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class test { /** * 反射:載入類的位元組碼 * * @throws SecurityException * @throws NoSuchMethodException */ public static void main(String[] args) throws Exception { refGetClass(); // 擷取並調用無參建構函式 refGetPublicConstructor(); // 擷取並調用私人的含參建構函式 refGetPrivateConstructor(); // 擷取並調用無參方法 fun refGetMethodWithNoArg(); // 擷取並調用有參數方法 fun refGetMethodWithArg(); // 擷取類的欄位 refGetField(); } private static void refGetField() throws Exception { Class clazz = Class.forName("com.yano.reflect.Person"); Constructor c = clazz .getDeclaredConstructor(new Class[] { String.class }); // 由於建構函式是 private 的,所以需要擷取控制許可權 c.setAccessible(true); Person p = (Person) c .newInstance(new Object[] { "I'm a reflect name!" }); Field f = clazz.getField("name"); Object value = f.get(p); Class type = f.getType(); System.out.println(type); if (type.equals(String.class)) { System.out.println((String) value); } System.out.println(); } private static void refGetMethodWithArg() throws Exception { Class clazz = Class.forName("com.yano.reflect.Person"); Constructor c = clazz.getConstructor(null); Person p = (Person) c.newInstance(null); Method method = clazz.getMethod("fun", new Class[] { String.class }); method.invoke(p, new Object[] { "I'm a reflect method!" }); System.out.println(); } private static void refGetMethodWithNoArg() throws Exception { Class clazz = Class.forName("com.yano.reflect.Person"); Constructor c = clazz.getConstructor(null); Person p = (Person) c.newInstance(null); Method method = clazz.getMethod("fun", null); method.invoke(p, null); System.out.println(); } private static void refGetPrivateConstructor() throws Exception { Class clazz = Class.forName("com.yano.reflect.Person"); Constructor c = clazz .getDeclaredConstructor(new Class[] { String.class }); // 由於建構函式是 private 的,所以需要屏蔽Java語言的訪問檢查 c.setAccessible(true); Person p = (Person) c .newInstance(new Object[] { "I'm a reflect name!" }); System.out.println(); } private static void refGetPublicConstructor() throws Exception { Class clazz = Class.forName("com.yano.reflect.Person"); Constructor c = clazz.getConstructor(null); Person p = (Person) c.newInstance(null); System.out.println(); } private static void refGetClass() throws ClassNotFoundException { // 載入類的3種方法 Class clazz = Class.forName("com.yano.reflect.Person"); Class clazz1 = new Person().getClass(); Class class2 = Person.class; System.out.println(); }}
文/被稱為L的男人(簡書作者)
原文連結:http://www.jianshu.com/p/53eb4e16d00e
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。