Java 反射(Reflect)詳解
一 首先我們的去知道什么是反射?
加載完類之后,在堆內(nèi)存的方法區(qū)中就產(chǎn)生了一個(gè)Class類型的對(duì)象 ,一個(gè)類只有一個(gè)Class對(duì)象,這個(gè)對(duì)象就包含了完整的類的結(jié)構(gòu)信息。我們可以通過(guò)這個(gè)對(duì)象看到類的結(jié)構(gòu)。這個(gè)對(duì)象就像一面鏡子,通過(guò)這個(gè)鏡子可以看到類的結(jié)構(gòu),所以我們形象的稱為:反射 ,或者說(shuō)動(dòng)態(tài)(運(yùn)行時(shí))獲取類信息和調(diào)用類方法
二(刨根問(wèn)底)知道是什么還需要知道什么“成分”組成反射?
想要去實(shí)現(xiàn)反射想要借助一些類分別是 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ò)類的全限定名獲取該類的 Class 對(duì)象
Class s1 =Class.forName(“com.ma.reflect.Student”);
3通過(guò)類名.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("獲得包+類"+c.getName());//獲得包+類
System.out.println("獲得類名"+c.getSimpleName());//獲得類名
//獲得類的屬性
System.out.println("-------------------------");
Field[] fields=c.getFields();//的到public類
for (Field field : fields) {
System.out.println("獲得類的Public 屬性"+field); }
System.out.println("-------------------------");
//獲得全部的類屬性
Field[] f1=c.getDeclaredFields();
for (Field field : f1) {
System.out.println("獲得類的全部屬性"+field); }
System.out.println("-------------------------");
//獲得指定屬性的值
Field name=c.getDeclaredField("age");
System.out.println("獲得指定了屬性的類型"+name);
System.out.println("-------------------------");
//獲得指定方法的值
Method[] methods=c.getMethods();
System.out.println("獲得所有的public方法");
for (Method method : methods) {
System.out.println("public類有"+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 修改類的私有屬性,由于是私有屬性,所以需要去關(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)建和控制任何類的對(duì)象,無(wú)需提前硬編碼目標(biāo)類
4.2反射的缺點(diǎn)
因?yàn)槭荍VM操作,所以對(duì)于性能來(lái)說(shuō)會(huì)有所下降。
容易對(duì)程序源碼造成一定的混亂。
五 反射的使用場(chǎng)合
在編譯時(shí)根本無(wú)法知道該對(duì)象或類可能屬于哪些類,程序只依靠運(yùn)行時(shí)信息來(lái)發(fā)現(xiàn)該對(duì)象和類的真實(shí)信息
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
JAVA復(fù)制數(shù)組和重置數(shù)組大小操作
這篇文章主要介紹了JAVA復(fù)制數(shù)組和重置數(shù)組大小操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
java面向?qū)ο笤O(shè)計(jì)原則之合成復(fù)用原則示例詳解
這篇文章主要介紹了java面向?qū)ο笤O(shè)計(jì)原則之合成復(fù)用原則的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2021-10-10
一個(gè)簡(jiǎn)單的Python名片管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了一個(gè)簡(jiǎn)單的Python名片管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01
springboot 配置日志 打印不出來(lái)sql的解決方法
這篇文章主要介紹了springboot 配置日志 打印不出來(lái)sql的解決方法,幫助大家更好的理解和使用springboot框架,感興趣的朋友可以了解下2020-11-11

