一、JAVA反射機制的簡單解釋:
? ? ? ? 是在程序運行狀態(tài)中,對與任意的一個類(class文件),都能知道這個類的所有屬性和方法;
? ? ? ? 對于任意一個對象,都能調(diào)用它的任意一個方法和屬性;
? ? ? ? 這種動態(tài)獲取的信息以及動態(tài)調(diào)用的對象的功能稱為java語言的反射機制。
? ? ? ? 動態(tài)獲取類中的信息,就是java的反射,理解為對類的解剖;
二、應(yīng)用場景:
? ? ? ? 對指定名稱的字節(jié)碼文件進行加載并獲取其中的內(nèi)容并調(diào)用;
? ? ? ? 大大的提高了程序的擴展性;
? ? ? ? 應(yīng)用簡單;面向配置文件開發(fā);
? ? ? ? 是根據(jù)名稱找到Demo.class配置文件,然后提取屬性與方法;
三、使用原理:
? ? ? ? 用于描述字節(jié)碼文件的類是Class類并且提供獲取字節(jié)碼文件中的內(nèi)容;
? ? ? ? 比如: 名稱? 字段? 構(gòu)造函數(shù)? 一般函數(shù)? 該類就可以獲取字節(jié)碼文件中的所有內(nèi)容;
? ? ? ? 即反射? 就是依靠該類完成的;
四、想要對一個類文件的進行解剖,只要獲取到該類的字節(jié)碼文件對象即可。
? ? 那么如何拿到一個類的字節(jié)碼文件對象(三種方法):
? ? 要想對字節(jié)碼文件進行解刨,必須要有字節(jié)碼文件的對象,獲取方法有三種:
? ? ? ? ? ? 1、object類中的getclass()方法,這種方法必須明確具體的類,并創(chuàng)建對象;
? ? ? ? ? ? ? ? ? ? Person p = new Person();
? ? ? ? ? ? ? ? ? ? Class clazz = p.getclass();
? ? ? ? ? ? 2、任何數(shù)據(jù)類型都具備一個靜態(tài)的屬性,class來獲取器對應(yīng)的class對象
? ? ? ? ? ? ? ? ? ? Class clazz = Person.class;? ? ? // 使用靜態(tài)成員,還是不夠擴展,
? ? ? ? ? ? 3、只要通過給定的類的字符串名稱就可以獲取該類,更為擴展,使用Class類中的方法完成,該方法就是forName();
? ? ? ? ? ? ? ? ? ? String className = "包路徑.Person";
? ? ? ? ? ? ? ? ? ? Class clazz = Class.forName(className);
? ? ? ? ? ? ? ? ? ? // 去項目中的.classpath中去找,并且這個Person類是要帶包名的(為項目中的? ? ? ? ? ? ? ? ? ? ? ? ? ? // classpath的并目錄下開始的包路徑)
? ? ? ? ? ? 這種方式只要有名稱即可,更為方便,擴展性更強。
獲取Class中的構(gòu)造函數(shù):
之前:
? ? ? ? ? ? Person p = new Person();
? ? ? ? ? ? 通過new方法創(chuàng)建實例,new是先根據(jù)被new的類名稱尋找該類的字節(jié)碼文件,并加進內(nèi)存,
并創(chuàng)建該字節(jié)碼的文件對象,并接著創(chuàng)建該字節(jié)文件的對應(yīng)的Person對象。
現(xiàn)在:
? ? ? ? ? ? String name = "cn.itcast.bean.Person";
? ? ? ? ? ? //尋找該名稱的類文件,并加載進內(nèi)存,并產(chǎn)生Class對象。
? ? ? ? ? ? Class clazz = Class.forName(name);
? ? ? ? ? ? //如何產(chǎn)生該類的對象呢?創(chuàng)建一個class文件的實例對象(object類型)。
? ? ? ? ? ? object obj = clazz.newInstance();? //通過調(diào)用空參的構(gòu)造函數(shù)
? ? ? ? ? ? 當(dāng)要獲取指定名稱的類中所體現(xiàn)的對象時,而該對象初始化不使用空參數(shù)構(gòu)造時:
? ? ? ? ? ? 通過指定的構(gòu)造函數(shù)進行對象的初始化,應(yīng)該先獲取到該構(gòu)造函數(shù)。通過字節(jié)碼文件對象即可完成是getConstructors()
? ? ? ? ? ? 該方法是:getConstructors(paramterTypes);? //獲取到指定的構(gòu)造函數(shù)對象。
? ? ? ? ? ? Constructors constructor = clazz.getConstructors(String.class, int.class);
? ? ? ? ? ? 通過構(gòu)造器對象的newInstance()方法進行對象的初始化。
? ? ? ? ? ? Object obj = constructor.newInstance("小明",38);
獲取Class中的字段:
? ? ? ? ? ? getFields() 獲取全部字段
? ? ? ? ? ? getField(String name) 獲取單一字段
? ? ? ? ? ? eg:
? ? ? ? ? ? ? ? ? ? Class clazz = Class.forName(name);
? ? ? ? ? ? ? ? ? ? Field field = clazz.getField("age");? //獲取的都是公共的字段
? ? ? ? ? ? ? ? ? ? Field field = clazz.getDeclaredField("gae");? //只獲取本類,但包含私有
? ? ? ? ? ? 字段設(shè)置值與獲取值:
? ? ? ? ? ? ? ? ? ? field.get(obj);? //獲取一個屬性值? 若為私有變量則對私有字段的訪問取消權(quán)限檢查,暴力訪問,不推薦。
? ? ? ? ? ? ? ? ? ? field.set(obj,89) //設(shè)置一個屬性值
獲取Class中的方法:
? ? eg:
? ? ? ? ? ? Method[] methods = clazz.getMethods();? //獲取的都是公共的方法?
? ? ? ? ? ? methods = getDeclaredMethods();? //獲取此類中的所有方法包括私有方法
? ? ? ? ? ? //獲取空參數(shù)一般方法
? ? ? ? ? ? Method method = clazz.getMethod("show",null);
? ? ? ? ? ? Object obj = clazz.newInstance();
? ? ? ? ? ? method.invoke(obj,null);
? ? ? ? ? ? //獲取有參數(shù)一般方法
? ? ? ? ? ? Method method = clazz.getMethod("paramMethod", String.class,int.class);
? ? ? ? ? ? //調(diào)用與空參數(shù)方法一致。