反射:框架設計的靈魂
框架:半成品軟件。可以在框架的基礎上進行軟件開發,簡化編碼。
概述
反射:將類的各個組成部分封裝爲其他對象,這就是反射機制。
好處:
1. 可以在程序運行過程中,操作這些對象。
2. 可以解耦,提高程序的可擴展性。
編譯完成後,.java和.class 都屬於源代碼階段, 程序運行,.class被類加載器加載到內存中時爲Class類對象階段,new出對象後爲Runtime階段。
獲取Class對象的方式
- Class.forName("全類名"):將字節碼文件加載進內存,返回Class對象,多用於配置文件,將類名定義在配置文件中。讀取文件加載類。
- 類名.class:通過類名的屬性class獲取,多用於參數的傳遞
- 對象.getClass():getClass()方法在Object類中定義着,多用於對象的獲取字節碼的方式
同一個字節碼文件(*.class)在一次程序運行過程中,只會被加載一次,不論通過哪一種方式獲取的Class對象都是同一個。
Class對象功能
獲取功能:
1. 獲取成員變量們
- Field[] getFields() :獲取所有public修飾的成員變量
- Field getField(String name) 獲取指定名稱的 public修飾的成員變量
- Field[] getDeclaredFields() 獲取所有的成員變量,不考慮修飾符
- Field getDeclaredField(String name) 獲取指定名稱的 public修飾的成員變量,不考慮修飾符
2. 獲取構造方法們
- 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() Class對象功能:
Field:成員變量
操作:
- void set(Object obj, Object value) 設置值
- get(Object obj) 獲取值
- setAccessible(true):暴力反射,忽略訪問權限修飾符的安全檢查。通常在使用private修飾的變量和方法前,要通過方法對象的該方法,setAccessible(true) ,將其權限打開。
Constructor:構造方法
創建對象:如果使用空參數構造方法創建對象,操作可以簡化:Class對象的newInstance方法
- T newInstance(Object... initargs)
Method:方法對象
執行方法:
- Object invoke(Object obj, Object... args)
獲取方法名稱:
- String getName:獲取方法名
demo
需求:寫一個"框架",不能改變該類的任何代碼的前提下,可以幫我們創建任意類的對象,並且執行其中任意方法
實現:
1. 配置文件
2. 反射
步驟:
1. 將需要創建的對象的全類名和需要執行的方法定義在配置文件中
2. 在程序中加載讀取配置文件
3. 使用反射技術來加載類文件進內存
4. 創建對象
5. 執行方法
public class Person {
private String name;
private int age;
public String a;
protected String b;
String c;
private String d;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
", d='" + d + '\'' +
'}';
}
public void eat(){
System.out.println("eat...");
}
public void eat(String food){
System.out.println("eat..."+food);
}
}
配置文件
className=cn.hello.Student
methodName=eat
反射
public static void main(String[] args) throws Exception {
//1.加載配置文件
//1.1創建Properties對象
Properties pro = new Properties();
//1.2加載配置文件,轉換爲一個集合
//1.2.1獲取class目錄下的配置文件
ClassLoader classLoader = ReflectTest.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("pro.properties");
pro.load(is);
//2.獲取配置文件中定義的數據
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
//3.加載該類進內存
Class cls = Class.forName(className);
//4.創建對象
Object obj = cls.newInstance();
//5.獲取方法對象
Method method = cls.getMethod(methodName);
//6.執行方法
method.invoke(obj);
}
執行結果
eat...
感謝關注
加油啊!