Java 反射(Reflect)詳解
一 首先我們的去知道什么是反射?
加載完類(lèi)之后,在堆內(nèi)存的方法區(qū)中就產(chǎn)生了一個(gè)Class類(lèi)型的對(duì)象 ,一個(gè)類(lèi)只有一個(gè)Class對(duì)象,這個(gè)對(duì)象就包含了完整的類(lèi)的結(jié)構(gòu)信息。我們可以通過(guò)這個(gè)對(duì)象看到類(lèi)的結(jié)構(gòu)。這個(gè)對(duì)象就像一面鏡子,通過(guò)這個(gè)鏡子可以看到類(lèi)的結(jié)構(gòu),所以我們形象的稱(chēng)為:反射 ,或者說(shuō)動(dòng)態(tài)(運(yùn)行時(shí))獲取類(lèi)信息和調(diào)用類(lèi)方法
二(刨根問(wèn)底)知道是什么還需要知道什么“成分”組成反射?
想要去實(shí)現(xiàn)反射想要借助一些類(lèi)分別是 class,Constructor,F(xiàn)ield,Method;
2.1 Class 對(duì)象的獲取及使用
吃飯的先拿碗筷,反射就得先找先找 Class
找Class的有三種方式
1實(shí)例化對(duì)象獲取該實(shí)例的 Class 對(duì)象
Person person = new Student();
Class s=person.getClass();
2通過(guò)類(lèi)的全限定名獲取該類(lèi)的 Class 對(duì)象
Class s1 =Class.forName(“com.ma.reflect.Student”);
3通過(guò)類(lèi)名.class
Class S2=Student.class;
2.2 拿到碗筷就得去盛飯,拿到了Class就得去操作,獲得屬性
代碼案例
package com.ma.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class reflectTest6 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { //反射 Class c=Class.forName("com.ma.reflect.User"); System.out.println("獲得包+類(lèi)"+c.getName());//獲得包+類(lèi) System.out.println("獲得類(lèi)名"+c.getSimpleName());//獲得類(lèi)名 //獲得類(lèi)的屬性 System.out.println("-------------------------"); Field[] fields=c.getFields();//的到public類(lèi) for (Field field : fields) { System.out.println("獲得類(lèi)的Public 屬性"+field); } System.out.println("-------------------------"); //獲得全部的類(lèi)屬性 Field[] f1=c.getDeclaredFields(); for (Field field : f1) { System.out.println("獲得類(lèi)的全部屬性"+field); } System.out.println("-------------------------"); //獲得指定屬性的值 Field name=c.getDeclaredField("age"); System.out.println("獲得指定了屬性的類(lèi)型"+name); System.out.println("-------------------------"); //獲得指定方法的值 Method[] methods=c.getMethods(); System.out.println("獲得所有的public方法"); for (Method method : methods) { System.out.println("public類(lèi)有"+method); } Method[] methods1=c.getDeclaredMethods(); System.out.println("獲得所有的public方法"); for (Method method : methods1) { System.out.println("所有的方法="+method); } System.out.println("-------------------------"); System.out.println("獲得所有的public構(gòu)造器"); Constructor[] constructors=c.getConstructors(); for (Constructor constructor : constructors) { System.out.println("public的構(gòu)造器"+constructor); } System.out.println("獲得所有的構(gòu)造器"); Constructor[] constructors1=c.getDeclaredConstructors(); for (Constructor constructor : constructors1) { System.out.println("所有的構(gòu)造器"+constructor); } } }
2.3 吃飽飯,我還想學(xué)做飯,找到Class,但是我想去獲取Class對(duì)象的實(shí)例。
Class user=Class.forName("com.ma.reflect.User");//獲得Class對(duì)象 //構(gòu)造對(duì)象 User user1=(User) user.newInstance();//無(wú)參方法 System.out.println(user1); //通過(guò)構(gòu)造器 創(chuàng)建有參方法 Constructor constructor=user.getDeclaredConstructor(String.class,int.class,int.class); User user2= (User) constructor.newInstance("myt",28,213); System.out.println(user2);
2.4 調(diào)用Class的實(shí)例對(duì)象的方法
Class user=Class.forName("com.ma.reflect.User");//獲得Class對(duì)象 User user3=(User) user.newInstance(); //通反射去獲取一個(gè)方法 Method setName=user.getDeclaredMethod("setName", String.class); //invoke激活 (對(duì)象,參數(shù)) setName.invoke(user3,"myt"); System.out.println(user3.getName());
2.5 修改類(lèi)的私有屬性,由于是私有屬性,所以需要去關(guān)閉程序的安全監(jiān)測(cè)。
//通過(guò)反射去調(diào)用方法
User user4=(User) user.newInstance(); Field name=user.getDeclaredField("name");//得到屬性 //***修改權(quán)限 去實(shí)現(xiàn)對(duì)私有屬性的修改 通過(guò)關(guān)閉程序的安全監(jiān)測(cè) name.setAccessible(true); name.set(user4,"tym"); //private的屬性無(wú)法直接去調(diào)用并且修改 System.out.println(user4.getName());
三反射的性能
3 .1 走了不同的路,就得比較不同路的對(duì)比(性能對(duì)比);
普通方法、反射、關(guān)閉安全檢測(cè)的反射
public class reflectTest8 { //普通方法調(diào)用 public static void test(){ User user=new User(); Long startTime=System.currentTimeMillis(); for (int i = 0; i < 100000000; i++) { user.getName(); } Long endTime=System.currentTimeMillis(); System.out.println("普通方法"+(endTime-startTime)+"ms"); } //反射方法調(diào)用 public static void test1() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user=new User(); Class c=Class.forName("com.ma.reflect.User"); Method getName=c.getDeclaredMethod("getName",null); Long startTime=System.currentTimeMillis(); for (int i = 0; i < 100000000; i++) { getName.invoke(user,null); } Long endTime=System.currentTimeMillis(); System.out.println("反射方法"+(endTime-startTime)+"ms"); } //反射方法 關(guān)閉檢測(cè)調(diào)用 public static void test2() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user=new User(); Class c=Class.forName("com.ma.reflect.User"); Method getName=c.getDeclaredMethod("getName",null); getName.setAccessible(true); Long startTime=System.currentTimeMillis(); for (int i = 0; i < 100000000; i++) { getName.invoke(user,null); } Long endTime=System.currentTimeMillis(); System.out.println("反射方法 關(guān)閉檢測(cè)"+(endTime-startTime)+"ms"); } public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { test(); test1(); test2(); } }
四反射的的優(yōu)缺點(diǎn)
4.1反射的優(yōu)點(diǎn)
反射提高了Java程序的靈活性和擴(kuò)展性,降低耦合性,提高自適應(yīng)能力。它允許程序創(chuàng)建和控制任何類(lèi)的對(duì)象,無(wú)需提前硬編碼目標(biāo)類(lèi)
4.2反射的缺點(diǎn)
因?yàn)槭荍VM操作,所以對(duì)于性能來(lái)說(shuō)會(huì)有所下降。
容易對(duì)程序源碼造成一定的混亂。
五 反射的使用場(chǎng)合
在編譯時(shí)根本無(wú)法知道該對(duì)象或類(lèi)可能屬于哪些類(lèi),程序只依靠運(yùn)行時(shí)信息來(lái)發(fā)現(xiàn)該對(duì)象和類(lèi)的真實(shí)信息
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
springboot?jpa?實(shí)現(xiàn)返回結(jié)果自定義查詢(xún)
這篇文章主要介紹了springboot?jpa?實(shí)現(xiàn)返回結(jié)果自定義查詢(xún)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02Java使用JSON實(shí)現(xiàn)處理中文亂碼和Date格式
這篇文章主要為大家詳細(xì)介紹了Java如何在項(xiàng)目中使用JSON實(shí)現(xiàn)處理中文亂碼和Date格式的功能,文中的示例代碼講解詳細(xì),需要的小伙伴可以參考一下2023-06-06SpringAop @Aspect織入不生效,不執(zhí)行前置增強(qiáng)織入@Before方式
這篇文章主要介紹了SpringAop @Aspect織入不生效,不執(zhí)行前置增強(qiáng)織入@Before方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Java面試為何阿里強(qiáng)制要求不在foreach里執(zhí)行刪除操作
那天,小二去阿里面試,面試官老王一上來(lái)就甩給了他一道面試題:為什么阿里的 Java 開(kāi)發(fā)手冊(cè)里會(huì)強(qiáng)制不要在 foreach 里進(jìn)行元素的刪除操作2021-11-11JavaWeb 實(shí)現(xiàn)多個(gè)文件壓縮下載功能
文件下載時(shí),我們可能需要一次下載多個(gè)文件,批量下載文件時(shí),需要將多個(gè)文件打包為zip,然后再下載。本文給大家分享實(shí)現(xiàn)思路及具體實(shí)現(xiàn)代碼,對(duì)javaweb實(shí)現(xiàn)文件壓縮下載功能感興趣的朋友一起學(xué)習(xí)吧2017-07-07Java實(shí)戰(zhàn)網(wǎng)上電子書(shū)城的實(shí)現(xiàn)流程
讀萬(wàn)卷書(shū)不如行萬(wàn)里路,只學(xué)書(shū)上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SSM+JSP+maven+Mysql實(shí)現(xiàn)一個(gè)網(wǎng)上電子書(shū)城,大家可以在過(guò)程中查缺補(bǔ)漏,提升水平2022-01-01Maven發(fā)布封裝到中央倉(cāng)庫(kù)時(shí)候報(bào)錯(cuò):no default secret key
這篇文章主要介紹了Maven發(fā)布封裝到中央倉(cāng)庫(kù)時(shí)候報(bào)錯(cuò):no default secret key,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-123分鐘純 Java 注解搭個(gè)管理系統(tǒng)的示例代碼
這篇文章主要介紹了3分鐘純 Java 注解搭個(gè)管理系統(tǒng)的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03