反射

---------------------- ASP.Net+Android+IOS開發.Net培訓、期待與您交流! ----------------------

 

反射

       Java程序中的各個Java類屬於同一類事物,描述這類事物的Java類名就是Class

       對比提問:衆多的人用一個什麼類表示?衆多的Java類用一個什麼類表示?

                Person java    Class

       對比提問:Person類代表人,它的實例對象就是張三,李四這樣一個個具體的人,Class類代表Java類,它的各個事例對象又分別對應    什麼呢?

              對應各個類的字節碼,如Person類的字節碼,ArrayList類的字節碼等等

              一個類被類加載器加載進入內存中,佔用了一片存儲空間,這個空間裏面的內容就是類的字節碼,不同的類的字節碼不同,所以它們在內存              中的內容是不同的

              這一個個空間可分別用一個個的對象來表示,這些對象顯然具有相同的類型。

       如何得到各個字節碼對象的事例對象(Class類型)

              1、類名.class,如:System.class

              2、對象.getClass(),如:new Date().getClass()

              3Class.forName("類名"); ,如:Class.forName("java.lang.String");

       九個預定義Class實例對象:

              八個基本數據類型(boolean,char,byte,short,int,lang,float,double

       數組類型的Class實例對象:

              class.isArray()

              總之,只要在源程序中出現的類型,都有各自的Class實例對象,如:int[]void

       如:

  1. package cn.itcast.day1;  
  2.   
  3. public class ReflectTest {  
  4.   
  5.     /** 
  6.      * @param args 
  7.      */  
  8.     public static void main(String[] args)throws Exception {  
  9.         // TODO Auto-generated method stub  
  10.         String str1 = "abc";  
  11.         Class cla1 = str1.getClass();  
  12.         Class cla2 = String.class;  
  13.         Class cla3 = Class.forName("java.lang.String");  
  14.         //驗證三種方法是不是同一份字節碼,答案都是true  
  15.         System.out.println(cla1==cla2);  
  16.         System.out.println(cla1==cla3);  
  17.           
  18.         System.out.println(cla1.isPrimitive());//判斷是否是一個基本數據類型  
  19.         System.out.println(int.class==Integer.class);//intInteger是不同類型,各自有自己的字節碼  
  20.         System.out.println(int.class==Integer.TYPE);//TYPE用來表示所包裝的那份基本類型的字節碼  
  21.         //數組出現的類型也有自己的字節碼,用isArray()判斷  
  22.         System.out.println(int[].class.isPrimitive());  
  23.         System.out.println(int[].class.isArray());  
  24.           
  25.     }  
  26.   

 

      反射概念:就是把JAVA類中的各種成分映射成相應的JAVA類。

       如:一個java類中用一個Class類的對象來表示,一個類中的組成部分:成員變量,方法,構造方法,包等等信息也用一個個的JAVA類來表示,就像汽車是一個類,汽車的發動機,變速箱等等也是一個個類。表示java類的Class類顯然就是提供一系列方法,來獲得其中的變量,方法和構造方    法,修飾符,包等等信息,這個信息就是用相應類的事例對象來表示,它們是FieldMethodConstructorPackage等等。

 

      Constructor類:

           1、概述:Constructor代表某個類的構造方法。

           2、獲取構造方法:

                 1、如何得到某個類的所有構造方法(如得到String類的所有構造方法):

                      Constructor[] cons = Class.forName(“java.lang.String”).getConstructors()

                 2、獲取某一個構造方法:

                      Constructor con =String.class.getConstructor(StringBuffer.class);        

            3、創建實例對象:

                 1、通常方式:String str = new String(new StringBuffer (”abc”));

                 2、反射方式:String str = (String)con.newInstance(new StringBuffer(“abc”)); 

             調用獲得的方法時要用到上面相同類型的實例對象,即兩個StringBuffer()要對應相等。

             NewInstance():構造出一個實例對象,每調用一次就構造一個對象。

             注意:上面的兩個地方①②都要用到StringBuffer,這必須是一致的。

             個是指定要帶StringBuffer參數類型的構造方法,即所需使用的是含StringBuffer類型的構造方法。

             個是用這個構造方法創建對象,要傳入的參數類型必須是StringBuffer

             4、Class.newInstance():創建一個對象,不帶參數的構造方法。

     

      Field類:

                            概述:Field類代表成員變量(字段)的反射。

                            如:

  1. public class ReflectPoint {  
  2.     private int x;  
  3.     public int y;  
  4.   
  5.     public String toString(){  
  6.         return str1+";" + str2 + ";" + str3;  
  7.     }  
  8. }  
  9. public class FieldTest(){  
  10. ReflectPoint pt1 = new ReflectPoint(3,5);  
  11.     //fieldXfieldY並不是對象身上的變量,而是類上的  
  12.     //要用它去取某個對象上的對應的值,傳入什麼對象,就取相應對象的值。  
  13.     Field fieldY = pt1.getClass().getField("y");  
  14.     System.out.println(fieldY.get(pt1));  
  15.     //獲取私有的成員變量  
  16. Field fieldX = pt1.getClass().getDeclaredField("x");  
  17.     fieldX.setAccessible(true);  
  18.     System.out.println(fieldX.get(pt1));  

 

           Method類:

                  1、概述:Method類代表某個類中的一個成員方法。調用某個對象身上的方法,要先得到方法,再針對某個對象調用。

                  2、專家模式:誰調用這個數據,就是誰在調用它的專家。

                  如人關門。調用者:是門調用管的動作,對象是門,因爲門知道如何執行關的動作,通過門軸之類的細節實現。指揮者:是人在指揮門做               關的動作,只是給門發出了關的信號,讓門執行。

                  總結:變量使用方法,是方法本身知道如何實現執行的過程,也就是方法對象調用方法,才執行了方法的每個細節的。

                  3、獲取某個類中的某個方法:(如String str = ”abc”

                          1、通常方式:str.charAt(1)

                          2、反射方式:

                                  Method charAtMethod = Class.forName(“java.lang.String”).getMethod(“charAt”,int.class);

                                  charAtMethod.invoke(str,1);

                                  說明:如果傳遞給Method對象的invoke()方法的第一個參數爲null,說明Method對象對應的是一個靜態方法

                   4、用反射方式執行某個main方法:

                           首先要明確爲何要用反射:在寫源程序時,並不知道使用者傳入的類名是什麼,但是雖然傳入的類名不知道,而知道的是這個類中                           的方法有main這個方法,所以可以通過反射的方式,通過使用者傳入的類名(可定義字符串型變量作爲傳入類名的入口,通過這個                           變量代表類名),內部通過傳入的類名獲取其main方法,然後執行相應的內容。

                如:

  1. //Method類演示  
  2. private static void methodTest(String [] args) throws Exception {  
  3.     String str1 = "abc";  
  4.     //一般方法:  
  5.     System.out.println(str1.charAt(1));  
  6.     //反射方法   
  7.     Method methodCharAt =  
  8.         Class.forName("java.lang.String").getMethod("charAt",int.class);  
  9.     System.out.println(methodCharAt.invoke(str1,1));  
  10.       
  11.     //用反射方式執行某個main方法  
  12.     //一般方式:  
  13.     Test.main(new String[]{"111","222","333"});  
  14.     System.out.println("-------");  
  15.       
  16.     //反射方式:  
  17.     String startingClassName = args[0];  
  18.     Method methodMain =  
  19.         Class.forName(startingClassName).getMethod("main",String[].class);  
  20.         //方案一:強制轉換爲超類Object,不用拆包  
  21.         methodMain.invoke(null,(Object)new String[]{"111","222","333"});  
  22.         //方案二:將數組打包,編譯器拆包後就是一個String[]類型的整體  
  23.         methodMain.invoke(null,new Object[]{new String[]{"111","222","333"}});  
  24.     }  
  25. //定義一個測試類  
  26. class Test{  
  27.     public static void main(String [] args){  
  28.         for(String arg : args){  
  29.             System.out.println(arg);  
  30.         }  
  31.     }  
  32. }

 

           數組的反射:

                 具有相同維數和元素類型的數組屬於同一個類型,即具有相同的Class實例對象(此處比較與值無關)

                 代表數組的Class實例對象的getSuperClass()方法返回的父類爲Object類對應的Class

                 基本類型的一維數組可以被當作Object類型使用,不能當作Object[]類型使用;非基本類型的一維數組,既可以當做Object類型使用,又                可以當做Object[]類型使用。

                 Arrays.asList()方法處理int[]String[]時的差異。

                 Array工具類用於完成對數組的反射操作。

 

---------------------- ASP.Net+Android+IOS開發.Net培訓、期待與您交流! ----------------------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章