反射的基石-Class類
- Java程序中的各個(gè)Java類屬于同一類事物因块,描述這類事物的Java類名就是Class揍堰。
- Class類描述了類的名稱,類的屬性诗轻,所屬的包,方法名稱等
- Classs類的實(shí)例對象:對應(yīng)各個(gè)類在內(nèi)存中的字節(jié)碼揭北,然后用該字節(jié)碼去創(chuàng)建多個(gè)實(shí)例對象扳炬。
三種得到字節(jié)碼對應(yīng)的實(shí)例對象
a)Class cls1 = Date.class
;
b)Date d1 = new Date(); Class cls2 = d1.getClass()
;
c)Class.forName("java.lang.String")
; //主要用這種比較多,參數(shù)可以通過配置文件配置搔体。forName的作用:返回字節(jié)碼恨樟。兩種方式:若不在內(nèi)存中,用類加載器加載到內(nèi)存中疚俱;已在內(nèi)存中劝术,直接返回。
- 9個(gè)預(yù)定義的Class類的實(shí)例對象(8個(gè)基本類型+1個(gè)Void)
a)int.class == Integer.Type --包裝的基本類型的字節(jié)碼void.class
b)程序中出現(xiàn)的類型呆奕,都有對應(yīng)的Class實(shí)例對象(字節(jié)碼)养晋,例如:int[],void
Class類的方法
-
isPrimitive()
//是否是基本類型 -
isArray()
//是否為數(shù)組 -
getConstructors()
Constructor[] //得到所有的構(gòu)造方法 -
getConstructor(Class<?>... paramType)
//得到某個(gè)構(gòu)造方法 -
getMethod(str,Class ...)
//返回公共方法;str:方法名梁钾;Classs ... :參數(shù)列表绳泉,獲得的是類上的方法 -
newInstance()
//調(diào)用該字節(jié)碼的無參的構(gòu)造方法 -
getField(str) Field
//返回類中可見的某個(gè)變量,類似getFields()姆泻;不是對象身上的變量零酪,而是類上的 變量,再調(diào)用get(obj)拇勃,調(diào)用具體的某個(gè)對象的變量的值 -
getDeclaredField(str) Field
//返回類中的某個(gè)變量 -
getSuperclass() Class
//獲取父類 -
getClassLoader().getResourceAsStream(String name) InputStream
//加載文件到內(nèi)存 -
getResourceAsStream(String name) InputStream
//加載文件到內(nèi)存
反射
把Java類中的各種成分映射成相應(yīng)的Java類四苇,如:Method,Constructor方咆,Package月腋,F(xiàn)ield等。
- 一個(gè)類中的每個(gè)成員都可以用相應(yīng)的反射API類的一個(gè)實(shí)例對象來表示。
- 反射會導(dǎo)致程性能下降(先獲得Constructor實(shí)例對象保存到內(nèi)存中)
Constructor類
- 得到某類所有的構(gòu)造方法
Constructor[] cons = String.class.getConstructors()
; - 得到某個(gè)具體的構(gòu)造方法
Constructor[] cons = String.class.getConstructor(StringBuffer.class)
; - Constructor類的方法:
newInstance(Object... obj)
//調(diào)用某個(gè)構(gòu)造方法來創(chuàng)建實(shí)例對象罗售,對比Class.newInstance()
Constructor cons = String.class.getConstructor(StringBuffer.class)
; //用到類型
String str = (String)cons.newInstance(new StringBuffer("abc"))
; //用到這個(gè)類型的對象辜窑;必須一致
Field類
-
get(obj) Object
//返回obj對象上對應(yīng)變量的值 set(obj,str)
-
setAccessible(boolean)
//是否允許訪問,如果是私有的變量寨躁,盡管getDeclaredField可以得到穆碎,但是不設(shè)置為true,還是會報(bào)錯(cuò) -
getType() Class<?>
//獲取成員變量的字節(jié)碼(Class類的實(shí)例對象)
Method
- invoke(obj,obj ... ) //obj:某個(gè)對象的這個(gè)方法职恳;obj ... :方法傳遞的參數(shù)所禀;關(guān)門的這個(gè)方法應(yīng)該是在門身上,而不是人放钦;變量在誰身上色徘,就該由誰來操作;invoke(null操禀,obj ....) 調(diào)用的是靜態(tài)方法
案例:啟動(dòng)java程序的main方法的參數(shù)一個(gè)字符串?dāng)?shù)組褂策,即public static void main(String[] args),用反射調(diào)用main方法颓屑,如何為invoke方法傳遞參數(shù)呢斤寂?jdk1.5語法,把整個(gè)數(shù)組當(dāng)做一個(gè)參數(shù)揪惦;jdk1.4語法遍搞,數(shù)組中的每一個(gè)元素當(dāng)做一個(gè)參數(shù),若把字符串?dāng)?shù)組傳遞給invoke方法器腋,為了兼容jdk1.4溪猿,肯定按1.4處理,所以用invoke(null,new String[]{"1","2"})報(bào)錯(cuò)
解決:invoke(null,(Object)new String[]{})或invoke(null,new Object[]{new String[]{}})
數(shù)組的反射
- 具有相同維數(shù)和元素類型的數(shù)組屬于同一類型纫塌,即具有相同的Class實(shí)例對象(字節(jié)碼)
-
Arrays數(shù)組工具類
輸出:
原因:因?yàn)锳rrays.asList(T ... a) 1.5诊县,Arrays.asLiist(Object[] a) 1.4,而a4可以按照1.4處理措左,a1不能賦值給Object[ ](因?yàn)閕nt不是一個(gè)Object)翎冲,所以按照1.5處理,相當(dāng)于一個(gè)參數(shù)媳荒,所以才會出現(xiàn)這樣的打印結(jié)果 - Array工具類用于完成對數(shù)組的反射操作
getLength(obj) static int
get(obj,int) static Object
HashCode
- HashCode僅對Hash類型的集合有效
- 通常情況下抗悍,一個(gè)類的兩個(gè)對象equals方法比較相同時(shí),它們的HashCode碼也應(yīng)該相同
- 當(dāng)一個(gè)對象被存進(jìn)Hash類型的集合后钳枕,不要去修改對象中參與HashCode計(jì)算的字段缴渊,否則會造成HashCode不一致,無法刪除對象鱼炒,導(dǎo)致內(nèi)存泄露