1.反射的定義
反射是:指程序可以訪問、檢測和修改它本身狀態(tài)或行為的一種能力
在java中反射主要通過以下兩個java特性來完成工作的涝开。
- Class 類
- java.lang.reflect field method constructor
在java中我們常用反射做以下的事情
- 獲取類型的相關信息
- 動態(tài)調用方法
- 動態(tài)構造對象
- 從程序集中獲得類型剪个。
2. 反射的原理
一段代碼要想在java中執(zhí)行,首先要把java源碼(.java文件)進行編譯從而生成機器碼(.class文件)耗帕,然后class文件會經(jīng)過類加載器加載到內(nèi)存中另玖,并在啟動main方法時候執(zhí)行佣赖。
在類加載過程中恰矩,ClassLoader會把類的引用加載到類方法區(qū),并且在堆內(nèi)存建立Class對象保存文件中的Class信息憎蛤。這個不是new出來的對象外傅,而是類的類型對象,每個類只有一個class對象蹂午,作為方法區(qū)類的數(shù)據(jù)結構的接口栏豺。jvm創(chuàng)建對象前,會先檢查類是否加載豆胸,尋找類對應的class對象奥洼,若加載好,則為你的對象分配內(nèi)存晚胡,初始化灵奖。
使用反射的好處是,你不必在jvm啟動的時候就知道所有可能需要的類的信息估盘,而是在程序運行過程中瓷患,根據(jù)程序的需要,動態(tài)加載類的信息遣妥,和在程序運行過程中動態(tài)獲取類的信息擅编,而且由于加載的是class文件,并且沒有規(guī)定這個文件的來源箫踩,所以可以從網(wǎng)絡爱态,數(shù)據(jù)庫等地方動態(tài)加載java信息。
最常用的地方應該就是java使用數(shù)據(jù)庫時候境钟,根據(jù)選擇的數(shù)據(jù)庫種類锦担,動態(tài)加載數(shù)據(jù)庫的驅動程序,而不是首先就建立所有數(shù)據(jù)庫驅動的對象慨削。
3. 實例
包括構造方法洞渔、屬性套媚、方法的獲取,以及方法的調用磁椒。
測試類
package com.reflect;
public class ReflectTest {
private int age = 10;
public String name = "1234";
public ReflectTest(int age){
this.age = age;
}
public ReflectTest(int age, String name){
this.age = age;
this.name = name;
}
public void disPlay(String dispaly){
System.out.println("The display method is execute!"+dispaly);
}
public void getName(String name){
System.out.println("The getName method is execute!");
}
}
反射類
package com.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
ReflectTest obj = new ReflectTest(12);
Class clazz = obj.getClass(); //獲取這個對象的class對象
Constructor[] constructors = clazz.getConstructors(); //獲取所有構造方法
Field[] fields = clazz.getDeclaredFields(); //獲取所有屬性(包括私有屬性),非declare獲取非私有
Method[] methods = clazz.getDeclaredMethods(); //獲取所有方法(包括私有方法),非declare獲取非私有
System.out.println("All Construct is: ");
for(Constructor constructor:constructors){
System.out.println(constructor.getName()+" "+constructor.getParameterTypes());
}
System.out.println("All Fields is: ");
for(Field field:fields){
System.out.println(field.getName());
}
System.out.println("All Method is: ");
for(Method method:methods){
System.out.println(method.getName());
}
//開源框架中常用反射機制以及invoke配合來完成某些工作堤瘤。
//第一個參數(shù)是具體調用該方法的對象
//第二個參數(shù)是執(zhí)行該方法的具體參數(shù)
Object[] objects = new String[1];
objects[0] = "123";
System.out.println("Begin to execute method by invoke");
for(Method method:methods){
method.invoke(obj, objects);
}
}
}