1. Java的反射機制
動態語言是指在程序運行時允許改變程序結構或者變量類型,從這個觀點看,JAVA和C++一樣,都不是動態語言。但Java它卻有着一個非常突出的動態相關機制:反射。
Java反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法;這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。
Java反射機制主要提供了以下功能:
(1)在運行時判斷任意一個對象所屬的類;
(2)在運行時構造任意一個類的對象;
(這一條在下面沒有展示實例,但在之前寫過的一篇Java中創建對象的5種方式中有所介紹,有興趣的可以參考查看。)
(3)在運行時判斷任意一個類所具有的成員變量和方法;
(4)在運行時調用任意一個對象的方法;
(5)生成動態代理。
2. Java反射API
反射API用來生成在當前Java虛擬機中的類、接口或者對象的信息。
Class類:反射的核心類,可以獲取類的屬性,方法等內容信息。
Field類:Java.lang.reflect.表示類的屬性,可以獲取和設置類的中屬性值。
Method類:Java.lang.reflect。表示類的方法,它可以用來獲取類中方法的信息或者執行方法
Construcor類:Java.lang.reflect。表示類的構造方法。
3.反射常見用法
3.1 判斷對象是否屬於反射得到的類(isInstance)
-
class S {
-
}
-
public class IsInstance {
-
public static void main(String args[]) {
-
try {
-
Class cls = Class.forName("S");
-
boolean b1 = cls.isInstance(new Integer(37));
-
System.out.println(b1);
-
boolean b2 = cls.isInstance(new S());
-
System.out.println(b2);
-
}
-
catch (Throwable e) {
-
System.err.println(e);
-
}
-
}
-
}
3.2 獲取某個反射類的所有屬性字段
-
-
-
-
-
-
-
-
public Field[] getProperty(Class ownerClass) throws Exception {
-
-
-
-
Field[] fields = ownerClass.getDeclaredFields();
-
-
-
for(int i=0;i<fields.length;i++){
-
System.out.println("屬性:"+fields[i]);
-
}
-
-
return fields;
-
}
3.3 獲取反射類的某個public屬性值
-
-
-
-
-
-
-
-
-
public Object getProperty(Object owner,String fieldName) throws Exception {
-
-
-
Class ownerClass = owner.getClass();
-
-
-
Field field = ownerClass.getField(fieldName);
-
-
-
Object property = field.get(owner);
-
-
-
System.out.println(fieldName+"的屬性值:"+property.toString());
-
-
return property;
-
-
}
3.4 獲取反射類的該中的所有方法
-
-
-
-
-
-
-
public Method[] getMethods(Class ownerClass) throws Exception {
-
-
-
-
Method[] methods = ownerClass.getDeclaredMethods();
-
-
-
for(int i=0;i<methods.length;i++){
-
System.out.println("方法:" +methods[i]);
-
}
-
-
return methods;
-
}
3.5 執行反射類的該中的某個方法
-
-
-
-
-
-
-
-
public Object invokeMethod(Object owner,String methodName,Object[] args) throws Exception {
-
-
-
Class ownerClass = owner.getClass();
-
-
-
Method method = ownerClass.getMethod(methodName, null);
-
-
-
Object result = method.invoke(owner, args);
-
-
-
System.out.println("結果返回值:"+ result);
-
-
return result;
-
}
實例演示方法:
-
-
-
-
public void refTest(){
-
String className = "com.java.reflecttest.Student";
-
-
try {
-
-
-
Class<?> stu = Class.forName(className);
-
Object objStu = stu.newInstance();
-
-
-
-
System.out.println("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
-
System.out.println("調用 getProperty 方法,獲取Student類的所有屬性");
-
getProperty(stu);
-
-
-
-
System.out.println("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
-
System.out.println("調用 getProperty 方法,獲取Student類的NAME屬性值");
-
getProperty(objStu,"NAME");
-
-
-
-
System.out.println("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
-
System.out.println("調用 getMethods 方法,獲取Student類的所有方法");
-
getMethods(stu);
-
-
-
System.out.println("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
-
System.out.println("調用 invokeMethod 方法,執行Student類的getInfo方法");
-
invokeMethod(objStu, "getInfo", null);
-
-
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
演示所用的Student類:
運行結果:
4. 反射的效率
在Stackoverflow上認爲反射比較慢的程序員主要有如下看法,如果你面試遇到了,可以這樣回答:
(1)驗證等防禦代碼過於繁瑣,這一步本來在link階段,現在卻在計算時進行驗證。
(2)產生很多臨時對象,造成GC與計算時間消耗。
(3)由於缺少上下文,丟失了很多運行時的優化,比如JIT(它可以看作JVM的重要評測標準之一)
當然,我個人的看法是,現代JVM也不是非常慢了,它能夠對反射代碼進行緩存以及通過方法計數器同樣實現JIT優化,所以反射不一定慢。更重要的是,很多情況下,你自己的代碼纔是限制程序的瓶頸。因此,在開發效率遠大於運行效率的的基礎上,大膽使用反射,放心開發吧。
文章轉自:http://blog.csdn.NET/xiaoxian8023/article/details/9206055
http://www.jianshu.com/p/f83556bcae59