1.反射:框架的設(shè)計(jì)的靈魂
框架:半成品軟件。
可以在框架的基礎(chǔ)上進(jìn)行軟件開發(fā),簡(jiǎn)化代碼
反射:將類的各個(gè)組成部分封裝為其他對(duì)象,這就是反射機(jī)制
- 好處:
1.在運(yùn)行過(guò)程中,操作 Class 里面的對(duì)象
2.可以解耦,可以提高程序的可擴(kuò)展性
java 代碼在計(jì)算機(jī)中經(jīng)歷的三個(gè)階段

image.png
源代碼階段:字節(jié)碼文件
類對(duì)象階段:把字節(jié)碼文件加載進(jìn)內(nèi)存
2.Class 對(duì)象功能:
獲取Class對(duì)象的方式:
- Class.forName("全類名"):將字節(jié)碼文件加載進(jìn)內(nèi)存,返回Class對(duì)象
多用于配置文件,將類名定義在配置文件中,讀取文件,加載類
Class cls1 = Class.forName("cn.itcast.domain.Person");
- 類名.class:通過(guò)類名的屬性class獲取
多用于參數(shù)的傳遞
Class cls2 = Person.class;
- 對(duì)象.getClass():getClass()方法在Object類中定義著。
多用于獲取對(duì)象的字節(jié)碼方式
Person p = new Person();
Class cls3 = p.getClass();
結(jié)論:同一個(gè)字節(jié)碼文件(*.class)在一次程序運(yùn)行過(guò)程中,只會(huì)被加載一次,不論通過(guò)哪一種方式獲取的 Class 對(duì)象都是同一個(gè)
獲取功能:
1.獲取成員變量們
- Field [] getFields(): 獲取所有的 public 修飾的成員變量
- Field [] getFields( String name):獲取指定名稱的 public 修飾的成員變量
- Field[] getDeclaredFields()
- Field getDeclaredField(String name)
2. 獲取構(gòu)造方法們
- Constructor<?>[] getConstructors()
- Constructor<T> getConstructor(類<?>... parameterTypes)
- Constructor<T> getDeclaredConstructor(類<?>... parameterTypes)
- Constructor<?>[] getDeclaredConstructors()
3. 獲取成員方法們
* Method[] getMethods()
* Method getMethod(String name, 類<?>... parameterTypes)
* Method[] getDeclaredMethods()
* Method getDeclaredMethod(String name, 類<?>... parameterTypes)
4. 獲取類名
* String getName()
詳解:
1.Field 成員變量
操作:
1.設(shè)置值
Field a = personClass.getField("a");
//獲取成員變量a 的值
Person p = new Person();
Object value = a.get(p);
System.out.println(value);
//設(shè)置a的值
a.set(p, "張三");
System.out.println(p);
2.獲取值
Field a = personClass.getField("a");
//獲取成員變量a 的值
Person p = new Person();
Object value = a.get(p);
System.out.println(value);
3.忽略訪問(wèn)權(quán)限修飾符的安全檢查
Field d = personClass.getDeclaredField("d");
//忽略訪問(wèn)權(quán)限修飾符的安全檢查
d.setAccessible(true);//暴力反射
Object value2 = d.get(p);
System.out.println(value2);
2.構(gòu)造方法
1.獲取構(gòu)造函數(shù)
Constructor constructor = personClass.getConstructor(String.class, int.class);
System.out.println(constructor);
// 結(jié)果:public cn.itcast.domain.Person(java.lang.String,int)
Constructor constructor1 = personClass.getConstructor();
System.out.println(constructor1);
// 結(jié)果:public cn.itcast.domain.Person()
2.給構(gòu)造函數(shù)設(shè)置值
Object person = constructor.newInstance("張三", 23);
System.out.println(person);
//結(jié)果:Person{name='張三', age=23, a='null', b='null', c='null', d='null'}
3.創(chuàng)建對(duì)象
Object person1 = constructor1.newInstance();
System.out.println(person1);
//結(jié)果:Person{name='null', age=0, a='null', b='null', c='null', d='null'}
3.成員方法
獲取指定名稱的方法
//獲取指定名稱的方法
Method eat_method = personClass.getMethod("eat");
Person p = new Person();
//執(zhí)行方法
eat_method.invoke(p);
//結(jié)果:eat...
獲取重載的方法 eat
Method eat_method1 = personClass.getMethod("eat", String.class);
eat_method1.invoke(p, "food");
//結(jié)果:eat...food
4..獲取類名
String className = personClass.getName();
System.out.println(className);
//結(jié)果:cn.itcast.domain.Person
3.反射小案例
可以創(chuàng)建任意類的對(duì)象,可以執(zhí)行任意類的方法
1.創(chuàng)建 file 文件 pro.properties
className=cn.itcast.domain.Person
methodName=eat
2.Refletest.java
//加載配置文件
//創(chuàng)建 Properties 對(duì)象
Properties pro = new Properties();
//加載配置文件,轉(zhuǎn)換為一個(gè)集合
ClassLoader classLoader = Refletest.class.getClassLoader();
//獲取 class 目錄下的配置文件
InputStream is = classLoader.getResourceAsStream("pro.properties");
pro.load(is);
//獲取配置文件中定義的數(shù)據(jù)
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
//3.加載該類進(jìn)內(nèi)存
Class cls = Class.forName(className);
//4.創(chuàng)建對(duì)象
Object obj = cls.newInstance();
//5.獲取方法對(duì)象
Method method = cls.getMethod(methodName);
//6.執(zhí)行方法
method.invoke(obj);
結(jié)果:

image.png
更改 pro.properties 為:
className=cn.itcast.domain.Student
methodName=sleep
結(jié)果:

image.png
總結(jié):要執(zhí)行某個(gè)類的某個(gè)方法,只需要更改 配置文件 pro.properties 即可