參考自: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
著作權歸作者所有,轉載請聯繫作者獲得授權,並標註“簡書作者”。
原文鏈接:http://www.jianshu.com/p/53eb4e16d00e
著作權歸作者所有,轉載請聯繫作者獲得授權,並標註“簡書作者”。