1 什么是反射
Java反射機(jī)制是在運(yùn)行狀態(tài)中
對于任意一個(gè)類,都能知道這個(gè)類的所以屬性和方法;
對于任何一個(gè)對象,都能夠調(diào)用它的任何一個(gè)方法和屬性;
這樣動(dòng)態(tài)獲取新的以及動(dòng)態(tài)調(diào)用對象方法的功能就叫做反射。
2Class類
Class可以說是反射能夠?qū)崿F(xiàn)的基礎(chǔ)
class關(guān)鍵字是在聲明java類時(shí)使用的;而Class 是java JDK提供的一個(gè)類,完整路徑為 java.lang.Class
對于每一種類,Java虛擬機(jī)都會(huì)初始化出一個(gè)Class類型的實(shí)例,每當(dāng)我們編寫并且編譯一個(gè)新創(chuàng)建的類就會(huì)產(chǎn)生一個(gè)對應(yīng)Class對象,并且這個(gè)Class對象會(huì)被保存在同名.class文件里。
當(dāng)我們new一個(gè)新對象或者引用靜態(tài)成員變量時(shí),Java虛擬機(jī)(JVM)中的類加載器系統(tǒng)會(huì)將對應(yīng)Class對象加載到JVM中,然后JVM再根據(jù)這個(gè)類型信息相關(guān)的Class對象創(chuàng)建我們需要實(shí)例對象或者提供靜態(tài)變量的引用值。
構(gòu)造器是私有的,只有JVM才可以調(diào)用這個(gè)構(gòu)造函數(shù)創(chuàng)建Class的對象
每個(gè)class(注意class是小寫,代表普通類)類,無論創(chuàng)建多少個(gè)實(shí)例對象,在JVM中都對應(yīng)同一個(gè)Class對象。
Class是反射能夠?qū)崿F(xiàn)的基礎(chǔ)的另一個(gè)原因是:Java反射包java.lang.reflect中的所有類都沒有public構(gòu)造方法,要想獲得這些類實(shí)例,只能通過Class類獲取。所以說如果想使用反射,必須得獲得Class對象。
3 反射缺點(diǎn)
性能問題。因?yàn)榉瓷涫窃?b>運(yùn)行時(shí)而不是在編譯時(shí),所有不會(huì)利用到編譯優(yōu)化,同時(shí)因?yàn)槭莿?dòng)態(tài)生成,因此,反射操作的效率要比那些非反射操作低得多。
安全問題。使用反射技術(shù)要求程序必須在一個(gè)沒有安全限制的環(huán)境中運(yùn)行。如果一個(gè)程序必須在有安全限制的環(huán)境中運(yùn)行,如Applet,那么這就是個(gè)問題了。
代碼問題。由于反射允許代碼執(zhí)行一些在正常情況下不被允許的操作(比如訪問私有的屬性和方法),所以使用反射可能會(huì)導(dǎo)致意料之外的副作用--代碼有功能上的錯(cuò)誤,降低可移植性。反射代碼破壞了抽象性,因此當(dāng)平臺(tái)發(fā)生改變的時(shí)候,代碼的行為就有可能也隨著變化。
作者:凱玲之戀
鏈接:http://www.itdecent.cn/p/10c29883eac1
來源:簡書
簡書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請聯(lián)系作者獲得授權(quán)并注明出處。
1獲取class對象
三種方式獲取Class對象:
Object類中的getClass方法。這也是最常見的產(chǎn)生Class對象的方法。想要用這種方式,必須要明確具體的類,并創(chuàng)建對象,麻煩。
Person p =newPerson();
Classclazz = p.getClass();
直接獲取某一個(gè)對象的class.任何數(shù)據(jù)類型都具備一個(gè)靜態(tài)的屬性.class來獲取其對應(yīng)的class對象。相對簡單,但還是要明確用到的類中的靜態(tài)成員。還是不夠擴(kuò)展
Classclazz = Person.class;
使用Class類中的forName靜態(tài)方法只要通過給定的類的字符串名稱就可以獲取該類,更為擴(kuò)展
.但是這里的className**需要類的完全限定名**,因?yàn)樗亲址?,和?dǎo)沒導(dǎo)包沒任何關(guān)系
Class clazz = Class.forName("com.example.hgx.Person");//得添加異常ClassNotFoundException
2反射構(gòu)造對象
?1創(chuàng)建不需要構(gòu)造參數(shù)的對象
通過class對象的newInstance生成對象。
Person p =newPerson();
Strint className ="com.example.hgx.Person";
Class clazz = Class.forName(className);
Objectobj = clazz.newInstance();
2創(chuàng)建需要構(gòu)造參數(shù)的對象
這時(shí)要通過Class對象獲取指定的Constructor對象,再調(diào)用Constructor對象的newInstance()方法來創(chuàng)建實(shí)例。
//獲取Person類帶一個(gè)(String,int)參數(shù)的構(gòu)造器
Strint className ="com.example.hgx.Person";
Class clazz = Class.forName(className);
Constructor constructor = clazz.getConstructor(String.class,int.class);
Object obj = constructor.newInstance("小明",24);
3反射獲取成員變量
getField: 訪問公有的成員變量
getDeclaredField:所有已聲明的成員變量。但不能得到其父類的成員變量
Strint className ="com.example.hgx.Person";
Class clazz = Class.forName(className);
Object obj = clazz.newInstance();//訪問public字段Field field = clazz.getField("name");
field.set(obj,"小明");
Object o = field.get(obj);//訪問private字段,要取消權(quán)限檢查.暴力訪問
Field field1 =clazz.getDeclaredField("age");
field1.setAccessible(true);
field1.set(obj,24);
Object o1 = field1.get(obj);
反射方式獲取方法
獲取某個(gè)Class對象的方法集合,主要有以下幾個(gè)方法:
-getDeclaredMethods()方法返回類或接口聲明的所有方法,包括公共、保護(hù)、默認(rèn)(包)訪問和私有方法,但不包括繼承的方法。
-getMethods()方法返回某個(gè)類的所有公用(public)方法,包括其繼承類的公用方法。
-getMethod方法返回一個(gè)特定的方法,其中第一個(gè)參數(shù)為方法名稱,后面的參數(shù)為方法的參數(shù)對應(yīng)Class的對象
Class clazz = Class.forName("com.example.hgx.Person");
Method[] methods = clazz.getMethods();//獲得公有方法
for(Method method: methods){ System.out.println(method);}
Method[] all_methods = clazz.getDeclaredMethods();//只獲取本類中的所有方法,包含私有//調(diào)用方法Method method1 = clazz.getMethod("show",null);
//Person中的show()方法,空參
Object obj = clazz.newInstance();method1.invoke(obj,null);
//調(diào)用帶參方法
Method method = clazz.getMethod("paramMethod",String.class,int.class);
Object obj1 = clazz.newInstance();
method.invoke(obj1,"小明",24);
invoke方法的參數(shù),一個(gè)是Object類型,也就是調(diào)用該方法的對象,