天天看點

Java中的反射邏輯

 1 .      反射是在運作狀态中,對于任意一個類(class檔案),都能夠知道這個類的所有屬性和方法;對于任意一個對象,都隻能都調用它的任意一個方法和屬性,這種動态擷取的資訊一級動态調用對象的方法的功能呢個稱為java 的反射機制。

      反射其實就是動态加載一個指定的類,并擷取該類中的所有的内容。而且将位元組碼檔案封裝成對象,并将位元組碼檔案中的内容都封裝成對象,這樣便于操作這些成員。就是把JAVA類中的各種成分反射成為相應的JAVA類簡單說:反射技術可以對一個類進行解剖

 2.      反射的好處:大大的增強了程式的擴充性。

 3.     反射的基本步驟:

          (1)、獲得Class對象,就是擷取到指定的名稱的位元組碼檔案對象。

          (2)、執行個體化對象,獲得類的屬性、方法或構造函數。

          (3)、通路屬性、調用方法、調用構造函數建立對象。

  4.    得到類的位元組碼檔案相同,這三種方式。

         1.  Class cls1=類名.class 相對簡單,還是需要明确類名

         2.  cls1.getclass();必須要明确具體的類,并建立對象

         3.  class.forName("完整的類名(帶包名)");

  5.  九個預定義的Class執行個體對象:

      (1).  Integer.class包裝類的位元組碼

      (2).  Integer.TYPE Integer中基本類型的位元組碼

      (3).  int.class==Integer.TYPE

      (4).  數組

                A. class.isPrimitive();

                B. class.isArray();

          隻要在源程式中出現的類型,都有各自的Class執行個體對象,例如 int[] void 等等

     (5).  建立類的對象

                String name="com.dsa.類名"; 

     (6).  尋找該名稱類檔案,并加載進記憶體,并非産生class對象:

                Class clazz=Class.forName(name); 

     (7) . 産生該類的對象:

                Object obj=clazz.newInstance();

     (8).  得到某一個指定構造方法:

                Constructor constructor= Class.forName("").getConstructor(String.class);

     (9).  建立執行個體對象

                Object obj=constructor.newInstance("abc");

 6.  成員變量 Filed類 代表某個類中的一個成員變量

        ReflectPoint pt1=new ReflectPoint(3,5);

        Filed filedy=pt1.getclsss().getFiled("Y"); //隻代表哪個對象

        Filed filedy=pt1.getclsss().getDeclaredField("x"); //擷取對象不管是私有還是被保護的

        filedy.setAccessible(true); //設定可以通路,暴力反射

        filedy.get(pt1); //取出Y的值

    将字段中的b全變成a

        Field[] fields=obj.getClass().getFields();//擷取全部對象

        for(Field field :fields){

             if(field.getType()==String.class){  //如果是字元串

                   String oldValue = (String)field.get(obj); //擷取字元串内容

                    String newValue = oldValue.replace('b','a'); //将字元串内容替換

                     field.set(obj,newValue); //将新值賦給對象   

7. Method類成員方法的反射

          擷取成員方法 反射形式:

               Method methodCharAt = String.class.getMethod("charAt"--方法名,int.class--這是參數類型,如果是空參函數則是 null);

               Object obj=clazz.newInstance(); methodCharAt.invoke(str1,1);

8. 數組的反射

  Class clazz=obj.getClass();

      if(clazz.isArray()){

            int len=array.getLength(obj);

                 for(int i=0;i<len;I==){

                      sopArray.get(obj,i))

              }

      }

9. 反射來擷取泛型資訊

         通過指定對應的Class對象,程式可以獲得該類裡面所有的Field,不管該Field使用private 方法public。獲得Field對象後都可以使用getType()來擷取其類型。

               Class<?> type = f.getType(); //獲得字段的類型

         但此方法隻對普通Field有效,若該Field有泛型修飾,則不能準确得到該Field的泛型參數,如Map<String,Integer>;為了獲得指定Field的泛型類型,我們采用:

              Type gType = f.getGenericType();

  得到泛型類型然後将Type對象強轉為ParameterizedType,其表示增加泛型後的類型

              Type getRawType();  //傳回被泛型限制的類型

              Type[] getActualTypeArguments(); //傳回泛型參數類型

10.利用反射來擷取泛型的類型(泛型資訊)

          步驟:

            (1).    擷取目前類

            (2).    擷取目标字段

            (3).  擷取包含泛型類型的類型 getGenericType()

            (4).  強轉至子類ParameterizedType( 因為Type沒有任何對應的方法)

            (5). 獲得泛型真正的類型 getActualTypeArguments()

11.例子:

package cn.itcast.day01;

import java.lang.reflect.Field;

import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;

import java.util.HashMap;

import java.util.Map;

public class GetGenericTypeDemo{

        Map<String,Integer> map = new HashMap<String,Integer>();

       public static void main(String[] args) throws Exception {

              Class c = GetGenericTypeDemo.class;

              Field f = c.getDeclaredField("map");

              System.out.println(f);

              System.out.println(f.getName()); //map

           // Class<?> getType() 傳回一個 Class 對象,它辨別了此 Field 對象所表示字段的聲明類型。

             Class cl = f.getType();

             System.out.println("獲得其類型:"+cl);//獲得其類型:interface java.util.Map

            Type t = f.getGenericType();//包含泛型的類型

            System.out.println(t);  //java.util.Map<java.lang.String, java.lang.Integer

            ParameterizedType pt = (ParameterizedType)t;//強轉到其子類

            t = pt.getRawType();//類型的類或接口

            System.out.println(t);

            Type[] ts = pt.getActualTypeArguments();

                   for (Type type : ts) {

                           System.out.println(type);

              }

      }

 }