k個一組翻轉連結串列
將類都各個組成部分封裝為其他物件,這就是反射機制
好處:
- 在程式的執行過程中,操作這些物件。
- 可以解耦,提高程式的可拓展性。
獲取class物件的方式(3種)
- class.forName(“全類名”); //將位元組碼檔案載入到記憶體,返回class物件
- 多用於配置檔案,將類名定義在配置檔案中,讀取檔案,載入類
- 類名.class:通過類名的屬性class屬性
- 多用於引數的傳遞
- 物件.getClass();:在Object中定義
- 多用於物件的獲取位元組碼的方式
結論:
同一個位元組碼檔案(*.class)在一次程式執行過程中,只會被載入一次,不論通過那種方式獲取的class物件都是同一個。
案例:
定義一個person類:
package cn.xue.domain; public class Person { private String name ; private Integer age; public Person(){} public Person(String name , Integer age) { this.name = name; this.age = age; } public void setName(String name) { this.name = name ; } public void setAge(Integer age) { this.age = age; } public String getName() { return this.name; } public Integer getAge() { return this.age; } public String toString() { return "年齡:"+this.name+"\n年齡:"+this.age; } }
建立使用類:
package cn.xue.reflect;
import cn.xue.domain.Person;
public class ReflectDemo {
public static void main(String[] args) throws Exception {
//1.Class.forName("全類名")
Class cls = Class.forName("cn.xue.domain.Person");
System.out.println(cls);
//2.類名
Class cls2 = Person.class;
System.out.println(cls2);
//3.物件.getClass();
Person p = new Person();
Class cls3 = p.getClass();
System.out.println(cls3);
/**
*比較三種方式獲得的類物件是否相同
*/
System.out.println(cls.equals(cls2)+"\n"+cls2.equals(cls3));
}
}
結論:三種方式獲得的類物件是相同的
使用class物件
-
獲取功能:
-
獲取成員變數們
-
Field[] getFields(); //獲取所有public修飾的成員變數
-
Field getField(String name); //獲取指定的public修飾的成員變數
-
Field[] getDeclardFields(); //獲取所有的成員變數,不考慮修飾符
-
Field getDeclardField();
-
-
獲取構造方法們
-
Constructor<?>[] getConstructors();
-
Constructor<?> getConstructor(類<?>… parameterTypes);
-
Constructor<?>[] getConstructors();
-
Constructor<?> getDeclardConstructor(類<?>… parameterTypes);
-
-
獲取成員方法們
-
Method[] getMethods();
-
Method getMethod(String name, 類<?>… parameterTypes);
-
Method[] getDeclardMethods();
-
Method getDeclardMethod(String name , 類<?>… parameterTypes);
-
-
獲取類名(獲取全類名)
- String getName();
-
Feild:成員變數
-
操作:
-
設定值:
void set(Object obj , Object value);
-
獲取值
void get(Object obj , Object value);
-
忽略訪問許可權修飾符的安全檢查
setAccessible(true); //暴力反射
-
-
-
constuctor:構造方法
-
建立物件:
- T newInstance(Object… initargs);
- 如果使用空引數構造方法建立物件,操作可以簡化,Class物件的newInstance方法
-
Method:方法物件
-
執行方法:
- invoke(Object obj , object… args); //獲取指定物件的方法
-
獲取方法名稱:
- String getName(); //獲取方法名
-
-
-
案例
需求:寫一個“框架”,不改變任意程式碼的情況下,可以建立任意一個類的物件,並且執行其中的任意方法
-
實現:
-
配置檔案(建立一個pro.properties檔案)
className=cn.xue.domain.Person
methodName=eat -
反射
-
-
步驟:
-
將需要建立的物件的全類名和需要執行的方法定義在配置檔案中
-
在程式中載入讀取配置檔案
-
使用反射技術載入類檔案進記憶體
Class.forName();
-
建立物件
-
執行方法
-
程式碼:
package cn.xue.reflect;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReflectFrame {
public static void main(String[] args) throws Exception {
//可以去建立任意類的物件,可以執行其任意方法
//1.載入配置檔案
//1.1建立properties物件
Properties pro = new Properties();//1.2載入配置檔案,轉換為一個集合
//1.2.1 獲取class目錄下的配置配置檔案
ClassLoader classLoader = ReflectFrame.class.getClassLoader();
InputStream in =classLoader.getResourceAsStream("pro.properties");
pro.load(in);
//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);
}
}