一:反射的基石 |
1:反射技術創建在jdk提供的Class類上,所以要掌握反射技術,首先要熟悉Class類。java
2:經過Class類就能夠獲得java類中方方面面的內容<如:java類中的:構造方法(Constructor)、屬性(field)、方法(method)>。spring
3:Class cls=?(?表明什麼,你知道嗎?)編程
注:?表明字節碼數組
4:什麼是字節碼?tomcat
注:java代碼編譯的時候,將java源程序翻譯成字節碼<.class>存儲到硬盤上,而後類加載器將字節碼加載到jvm的內存中,生成一個又一個java對象。 框架
5:獲得字節碼的三種方式:jvm
String str1="abc"ide
Class cls1=str1.getClass();<經過對象獲得字節碼>測試
Class cls2=String.class;<經過類獲得字節碼>this
Class cls3=Class.forName("java.lang.String");<經過包名獲得字節碼>
注:獲得了一個類的字節碼,那麼就能夠獲得字節碼的所有成分,下面將一一介紹.
6:同一類型的字節碼相同嗎?
System.out.println(cls1==cls2);返回:true
System.out.println(cls1==cls3);返回:true
注:說明同一類型的字節碼只有一份,同一類型的字節碼是相同的。
二:字節碼的簡單應用<檢測數據的類型> |
1: String str1="abc";
Class cls1=str1.getClass();
//測試String是否爲基本類型的字節碼,返回false;由於:String是一個類 System.out.println(cls1.isPrimitive());
2: //int是基本類型的字節碼,返回true
System.out.println(int.class.isPrimitive())
3: //int是基本類型,Integer是類,所以返回:false
System.out.println(int.class==Integer.class);
4: //包裝類型的基本類型的字節碼比較,返回true
System.out.println(int.class==Integer.TYPE);
5://數組不是基本類型,返回false
System.out.println(int[].class.isPrimitive());
三:反射調用類中構造方法 |
//從String類字節碼中得的:參數爲:StringBuffer的構造方法類 Constructor cons=String.class.getConstructor(StringBuffer.class);
//用獲得的構造方法類來建立一個String類型的實例
String str3=(String)cons.newInstance(new StringBuffer("abcd"));
//用獲得的實例調用方法
System.out.println(str3.charAt(3));
四:反射獲取類中的屬性--簡單應用 |
1:定義類(ReflectPoint)<下面用反射技術獲取該類的屬性>以下:
public class ReflectPoint {
private int x;//私有的屬性,注意看下面,反射怎樣訪問私有屬性!
public int y;
public String str1="bal";
public String str2="bseerb";
public String str3="hjke";
/**
* 注意:右鍵->source-Construtor能夠自動生成構造方法
* @param x
* @param y
*/
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;}
public String toString(){
return str1+":"+str2+":"+str3;
}}
2:使用反射技術,從ReflectPoint字節碼中獲得屬性y,代碼以下:
ReflectPoint rfp1=new ReflectPoint(3, 5);
//從ReflectPoint的字節碼中獲得名爲y的屬性
Field fieldY=rfp1.getClass().getField("y");
//從rfp1這個對象上去取值
System.out.println(fieldY.get(rfp1)); 結果爲:5
3:使用反射技術,從ReflectPoint字節碼中獲得私有屬性x,代碼以下:
ReflectPoint rfp1=new ReflectPoint(3, 5);
Field fieldX=rfp1.getClass().getDeclaredField("x");
//由於x設置的權限爲:private,所以設置強制性訪問變量,這叫暴力反射 ,
fieldX.setAccessible(true);
System.out.println(fieldX.get(rfp1)); 結果爲:3
五:反射改變類中的屬性值-綜合案例應用 |
1:問題?
將類名爲:ReflectPoint類中的String類型的成員變量對應的字符串內容的 "b"-改成-->"a"
2:定義類以下<用反射來改變這個類中的屬性>:
public class ReflectPoint {
public String str1="bal";
public String str2="bseerb";
public String str3="hjke";
}
3:反射方法代碼:
private static void changeStringValue(Object obj) throws IllegalArgumentException, IllegalAccessException {
//獲得obj字節碼中的所有屬性
Field[] fields=obj.getClass().getFields();//遍歷
for(Field field:fields){
//若是是String類型
if(field.getType()==String.class){
//取得值
String oldValue=(String) field.get(obj);
String newValue=oldValue.replace('b','a');
field.set(obj, newValue);
} }}
4:測試代碼:
ReflectPoint rfp1=new ReflectPoint();
changeStringValue(rfp1);
5:結果:
str1=aal str2 = aseera str3 = hjke 反射改變屬性值成功!
六:反射調用類中的方法 |
1:經過反射調用string類中charAt方法
String str1="abc";
//從string字節碼中獲得名爲:charAt,參數類型爲int.class的方法
Method methodChAt=String.class.getMethod("charAt",int.class); //注:invoke(str1,1)表示:對象str1調用charAt方法,傳入參數爲:1
System.out.println(methodChAt.invoke(str1,1));
七:總結 |
1:掌握了以上知識,就掌握了java反射機制的基礎和精髓部分。但運用反射機制到實際軟件系統中,在反射的世界裏,纔剛剛開始。
2:反射通常用於開發框架<如:struct/spring/Hibernate>,這些框架都是以反射技術做爲支撐的。
3:掌握了反射技術便於讀懂較深刻的java代碼<借張孝祥的話>,我也有這樣的體會。<研究tomcat源碼時候,裏面就運用了大量的反射技術>。
ps:在編程道路上|我纔剛剛起步|加油|堅持!
2012-10-4 coder:亮仔