摘要:簡(jiǎn)單說(shuō)反射技術(shù)可以對(duì)一個(gè)類進(jìn)行解剖。反射的基本步驟獲得對(duì)象,就是獲取到指定的名稱的字節(jié)碼文件對(duì)象。所以一般情況下,被反射的類,內(nèi)部通常都會(huì)提供一個(gè)公有的空參數(shù)的構(gòu)造函數(shù)。
定義
其實(shí)就是動(dòng)態(tài)加載一個(gè)指定的類,并獲取該類中的所有的內(nèi)容。 而且將字節(jié)碼文件封裝成對(duì)象,并將字節(jié)碼文件中的內(nèi)容都封裝成對(duì)象,這樣便于操作這些成員。 簡(jiǎn)單說(shuō):反射技術(shù)可以對(duì)一個(gè)類進(jìn)行解剖。
反射的好處:
大大的增強(qiáng)了程序的擴(kuò)展性。
反射的基本步驟:
獲得Class對(duì)象,就是獲取到指定的名稱的字節(jié)碼文件對(duì)象。 實(shí)例化對(duì)象,獲得類的屬性、方法或構(gòu)造函數(shù)。 訪問(wèn)屬性、調(diào)用方法、調(diào)用構(gòu)造函數(shù)創(chuàng)建對(duì)象。
獲取這個(gè)Class對(duì)象,有三種方式:
1:通過(guò)每個(gè)對(duì)象都具備的方法getClass來(lái)獲取。弊端:必須要?jiǎng)?chuàng)建該類對(duì)象,才可以調(diào)用getClass方法。 2:每一個(gè)數(shù)據(jù)類型(基本數(shù)據(jù)類型和引用數(shù)據(jù)類型)都有一個(gè)靜態(tài)的屬性class。弊端:必須要先明確該類。 前兩種方式不利于程序的擴(kuò)展,因?yàn)槎夹枰诔绦蚴褂镁唧w的類來(lái)完成。 3:使用的Class類中的方法,靜態(tài)的forName方法。 指定什么類名,就獲取什么類字節(jié)碼文件對(duì)象,這種方式的擴(kuò)展性最強(qiáng),只要將類名的字符串傳入即可。 // 1. 根據(jù)給定的類名來(lái)獲得 用于類加載 String classname = "cn.itcast.reflect.Person";// 來(lái)自配置文件 Class clazz = Class.forName(classname);// 此對(duì)象代表Person.class // 2. 如果拿到了對(duì)象,不知道是什么類型 用于獲得對(duì)象的類型 Object obj = new Person(); Class clazz1 = obj.getClass();// 獲得對(duì)象具體的類型 // 3. 如果是明確地獲得某個(gè)類的Class對(duì)象 主要用于傳參 Class clazz2 = Person.class;反射的用法
//需要獲得java類的各個(gè)組成部分,首先需要獲得類的Class對(duì)象,獲得Class對(duì)象的三種方式: Class.forName(classname)用于做類加載 obj.getClass()用于獲得對(duì)象的類型 類名.class 用于獲得指定的類型,傳參用 //反射類的成員方法: Class clazz = Person.class; Method method = clazz.getMethod(methodName, new Class[]{paramClazz1, paramClazz2}); method.invoke(); //反射類的構(gòu)造函數(shù): Constructor con = clazz.getConstructor(new Class[]{paramClazz1, paramClazz2,...}) con.newInstance(params...) //反射類的屬性: Field field = clazz.getField(fieldName); field.setAccessible(true); field.setObject(value);
獲取了字節(jié)碼文件對(duì)象后,最終都需要?jiǎng)?chuàng)建指定類的對(duì)象:
創(chuàng)建對(duì)象的兩種方式(其實(shí)就是對(duì)象在進(jìn)行實(shí)例化時(shí)的初始化方式): 調(diào)用空參數(shù)的構(gòu)造函數(shù):使用了Class類中的newInstance()方法。 調(diào)用帶參數(shù)的構(gòu)造函數(shù):先要獲取指定參數(shù)列表的構(gòu)造函數(shù)對(duì)象, 然后通過(guò)該構(gòu)造函數(shù)的對(duì)象的newInstance(實(shí)際參數(shù)) 進(jìn)行對(duì)象的初始化。
綜上所述,第二種方式,必須要先明確具體的構(gòu)造函數(shù)的參數(shù)類型,不便于擴(kuò)展。
所以一般情況下,被反射的類,內(nèi)部通常都會(huì)提供一個(gè)公有的空參數(shù)的構(gòu)造函數(shù)。
// 如何生成獲取到字節(jié)碼文件對(duì)象的實(shí)例對(duì)象。 Class clazz = Class.forName("cn.itcast.bean.Person");//類加載 // 直接獲得指定的類型 clazz = Person.class; // 根據(jù)對(duì)象獲得類型 Object obj = new Person("zhangsan", 19); clazz = obj.getClass(); Object obj = clazz.newInstance();//該實(shí)例化對(duì)象的方法調(diào)用就是指定類中的空參數(shù)構(gòu)造函數(shù),給創(chuàng)建對(duì)象進(jìn)行初始化。當(dāng)指定類中沒(méi)有空參數(shù)構(gòu)造函數(shù)時(shí),該如何創(chuàng)建該類對(duì)象呢?請(qǐng)看method_2(); public static void method_2() throws Exception { Class clazz = Class.forName("cn.itcast.bean.Person"); //既然類中沒(méi)有空參數(shù)的構(gòu)造函數(shù),那么只有獲取指定參數(shù)的構(gòu)造函數(shù),用該函數(shù)來(lái)進(jìn)行實(shí)例化。 //獲取一個(gè)帶參數(shù)的構(gòu)造器。 Constructor constructor = clazz.getConstructor(String.class,int.class); //想要對(duì)對(duì)象進(jìn)行初始化,使用構(gòu)造器的方法newInstance(); Object obj = constructor.newInstance("zhagnsan",30); //獲取所有構(gòu)造器。 Constructor[] constructors = clazz.getConstructors();//只包含公共的 constructors = clazz.getDeclaredConstructors();//包含私有的 for(Constructor con : constructors) { System.out.println(con); } }反射指定類中的方法
//獲取類中所有的方法。 public static void method_1() throws Exception { Class clazz = Class.forName("cn.itcast.bean.Person"); Method[] methods = clazz.getMethods();//獲取的是該類中的公有方法和父類中的公有方法。 methods = clazz.getDeclaredMethods();//獲取本類中的方法,包含私有方法。 for(Method method : methods) { System.out.println(method); } } //獲取指定方法; public static void method_2() throws Exception { Class clazz = Class.forName("cn.itcast.bean.Person"); //獲取指定名稱的方法。 Method method = clazz.getMethod("show", int.class,String.class); //想要運(yùn)行指定方法,當(dāng)然是方法對(duì)象最清楚,為了讓方法運(yùn)行,調(diào)用方法對(duì)象的invoke方法即可,但是方法運(yùn)行必須要明確所屬的對(duì)象和具體的實(shí)際參數(shù)。 Object obj = clazz.newInstance(); method.invoke(obj, 39,"hehehe");//執(zhí)行一個(gè)方法 } //想要運(yùn)行私有方法。 public static void method_3() throws Exception { Class clazz = Class.forName("cn.itcast.bean.Person"); //想要獲取私有方法。必須用getDeclearMethod(); Method method = clazz.getDeclaredMethod("method", null); // 私有方法不能直接訪問(wèn),因?yàn)闄?quán)限不夠。非要訪問(wèn),可以通過(guò)暴力的方式。 method.setAccessible(true);//一般很少用,因?yàn)樗接芯褪请[藏起來(lái),所以盡量不要訪問(wèn)。 } //反射靜態(tài)方法。 public static void method_4() throws Exception { Class clazz = Class.forName("cn.itcast.bean.Person"); Method method = clazz.getMethod("function",null); method.invoke(null,null); }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/73209.html
摘要:在該配置中,加入這個(gè)方法的話,表明使用了該配置的地方,就會(huì)禁用該模塊使用容災(zāi)降級(jí)的功能添加訪問(wèn)層添加電影微服務(wù)啟動(dòng)類電影微服務(wù),定制,一個(gè)功能禁用,另一個(gè)功能啟用。 SpringCloud(第 016 篇)電影微服務(wù),定制Feign,一個(gè)Feign功能禁用Hystrix,另一個(gè)Feign功能啟用Hystrix - 一、大致介紹 1、在一些場(chǎng)景中,部分功能需要使用斷路器功能,部分功能不需...
摘要:反射機(jī)制一結(jié)合官方通過(guò)編寫的反射教程,復(fù)習(xí)一下反射的知識(shí)。反射的概念反射是一種在運(yùn)行時(shí)獲取以及修改應(yīng)用行為的一種工具。因?yàn)榉瓷湫枰獎(jiǎng)討B(tài)的解析類的信息,相比于非反射使用的方式要慢。反射需要獲取一定的運(yùn)行時(shí)權(quán)限,在特定的安全環(huán)境下不一定存在。 Java反射機(jī)制(一) 結(jié)合Oracle官方通過(guò)JDK8編寫的反射教程,復(fù)習(xí)一下反射的知識(shí)。結(jié)尾篇補(bǔ)一個(gè)小例子。 主要內(nèi)容 這次博客的主要內(nèi)容就是簡(jiǎn)...
摘要:可以通過(guò)提供的方法,獲取對(duì)象,具體如下方法返回值方法名稱方法說(shuō)明返回一個(gè)指定參數(shù)的對(duì)象,該對(duì)象反映此對(duì)象所表示的類或接口的指定已聲明方法。 我來(lái)學(xué)習(xí)反射 1.為什么我們要學(xué)習(xí)反射? 通過(guò)反射機(jī)制可以獲取到一個(gè)類的完整信息,例如:所有(包含private修飾)屬性和方法,包信息等。 換句話說(shuō),Class本身表示一個(gè)類的本身,通過(guò)Class可以完整獲取一個(gè)類中的完整結(jié)構(gòu),包含此類中的方法定...
摘要:簡(jiǎn)介參考指南參考指南中文全文搜索引擎顧名思義,是做收索用的,因?yàn)槠胀ǖ乃阉髟跀?shù)據(jù)量小的時(shí)候,能應(yīng)對(duì)自如,但是當(dāng)數(shù)據(jù)量上千萬(wàn),或者上億的時(shí)候。 sphinx簡(jiǎn)介參考指南參考指南sphinx API中文 sphinx 全文搜索引擎:顧名思義,是做收索用的,因?yàn)槠胀ǖ乃阉髟跀?shù)據(jù)量小的時(shí)候,能應(yīng)對(duì)自如,但是當(dāng)數(shù)據(jù)量上千萬(wàn),或者上億的時(shí)候。純粹的sql搜索顯得緩慢,無(wú)力。因而為了提高用戶體驗(yàn),增...
閱讀 2669·2023-04-26 00:42
閱讀 2815·2021-09-24 10:34
閱讀 3827·2021-09-24 09:48
閱讀 4163·2021-09-03 10:28
閱讀 2584·2019-08-30 15:56
閱讀 2781·2019-08-30 15:55
閱讀 3272·2019-08-29 12:46
閱讀 2251·2019-08-28 17:52