Java基礎加強-反射機制

反射的基石 -> Class 類(字節碼)

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

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

1.類名.class  

2.對象.getClass

3.Class.forName("類名");(1.先忘內存中找,是否有這個字節碼  有的話,就是用,沒有的話 就使用類裝載器的方式,得到字節碼)

/*這三種方式得到的字節碼  都是同一份  是一樣的*/

九個預定義Class實例對象(八種基本數據類型 + void )

1.Class.isPrimitive 判斷是否爲預定義的實例對象

2.int.class == Integer.TYPE  (Integer.TYPE 得到該被包裝類型的字節碼)

3.int.class != Integer.class  (這是兩種不同的類型,字節碼也不同)



反射

/*反射就是把Java類中的各種成分(成員變量,方法,構造方法,包等)映射成相應的java類。*/

1.得到某個類的構造方法  Constructor

Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class)

Class.newInstance()方法  調用默認無參構造方法創建對象(用到了緩存機制來保存默認構造方法的實例對象)



2.成員變量的反射  Field

Field name = Class.forName("xxx.xxx.Person").getField("name");  //name不是某個對象(person)上的變量,而是某個類(Person)上的,要用它去取某個對象上對應的值

field.get(person);//需指定是哪個對象的成員變量


3.成員方法的反射  Method

  String str1 = "abc"

  Mehod methodCharAt = String.class.getMethod("charAt",int.class);   //得到某個類的成員方法

  System.out.println(methodCharAt.invoke(str1,1));   /*結果:b*/     //調用哪個對象的該方法,傳遞什麼參數

  如果invoke第一個參數傳遞爲 null ,說明調用該類的一個靜態方法

  
  /*

   * 人在黑板上畫圓,涉及三個對象,畫圓需要圓心和半徑,但是是私有的,畫圓的方法

   * 分配給人不合適。
   * 
   * 司機踩剎車,司機只是給列車發出指令,剎車的動作還需要列車去完成。
   * 

   * 面試經常考面向對象的設計,比如人關門,人只是去推門。

   * 

   * 這就是專家模式:誰擁有數據(private),誰就是專家,方法就分配給誰

   */
   

4.用反射方法執行某個類中的main方法

  main方法所需的參數是一個字符串數組,當反射調用這個main方法時,invoke傳遞參數時不能直接給一個字符串數組參數,因爲編譯的時候會將該字符串數組拆開,變成多個參數,

    而main方法只要一個參數,故報錯   解決辦法:將傳遞的字符串數組封裝成一個Object對象 或者 一個Object[] 對象

    

5.數組的反射

具有相同維數和元素類型的數組屬於同一個類型,即具有相同的Class實例對象

1.所有的數組

int[][]a1 = new int[3][3];

Object[] o1 = a1;     /*正確的,int[]  屬於Object*/

2.八大基本數據類型不繼承於Object

int[] a2 = new int[3];

Object[] o2 = a2;   /*錯誤的,int不屬於Object*/


注:Arrays.asList()方法,在jdk 1.4 中,由於 /*沒有可變參數*/,接收的參數時Object[] ,在jdk 5.0 中 接收的參數是一個可變參數

故,當System.out.println(Arrays.asList(String[])); 會打印出String數組中的元素的值  因爲這裏是 /*jdk1.4 去編譯*/,

當System.out.println(Arrays.asList(int[]));  因爲 /*int不屬於Object*/,所以 /*jdk1.4 無法編譯 而是5.0 去編譯(只會解析一個參數)*/,此時無法打印出元素,而是打印對象
 

6.ArrayList(有序可重複)和HashSet(無序不可重複)

存數據到ArrayList中時,一個對象一個空間,即使如果這兩個數據相互equals,同樣是按順序放到ArrayList中  

而HashSet,是一整塊混亂的空間,如果存數據時,兩個數據equals,後面的那個數據不會存進去


Set集合想要保證元素不重複,可兩個元素是否重複應該依據什麼來判斷呢?( /*先調用新元素HashCode方法,得到物理位置,如果該位置沒有元素,那新元素就放到這裏,如果有,再equals*/)

這就是Object.equals方法了。但是,如果每增加一個元素就檢查一次,那麼當元素很多時,後添加到集合中的元素比較的次數就非常多了。

初學者可以這樣理解,hashCode方法實際上返回的就是對象存儲的物理地址(實際可能並不是)。  

當集合要添加新的元素時, /*先調用這個元素的hashCode方法*/,就一下子能定位到它應該放置的物理位置上。

如果這個位置上沒有元素,它就可以直接存儲在這個位置上,不用再進行任何比較了;如果這個位置上已經有元素了,就調用它的equals方法與新元素進行比較,相同的話就不存了,不相同就散列其它的地址 


注:java中的內存泄漏,比如某些東西用不到了,想從內存中移除它,釋放內存,

當一個對象被存儲進HashSet集合中以後,就不能修改這個對象中那些參與計算哈希值的字段了,否則, /*對象修改後的哈希值與最初存儲進HashSet集合中時的哈希值

就不同了*/,導致無法從HashSet集合中單獨刪除當前對象,從而造成 /*內存泄漏*/


7.反射的作用->實現框架功能

框架要解決的核心問題,我在框架時,你這個用戶可能還在上小學 還不會寫程序,我寫的框架程序怎樣才能調用到你以後寫的類呢,(不知道會寫出什麼類)

因爲在寫程序時,無法知道直接知道要被調用的類名,所以,在程序中,無法直接new某個類的實例對象,而要用到反射來做 (也需要讀取配置文件)

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