全面剖析java反射機制

 

 一:反射的基石

 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:亮仔

相關文章
相關標籤/搜索