反射機(jī)制作用
- 在運(yùn)行時(shí)分析類的能力
- 在運(yùn)行時(shí)查看對(duì)象
- 實(shí)現(xiàn)通用的數(shù)組操作代碼
反射機(jī)制的實(shí)現(xiàn)
采用Class類和java.lang.reflect 類庫(kù)一起實(shí)現(xiàn) <反射>機(jī)制
- Class 類: 代表一個(gè)目標(biāo)類鸳劳。
- Field 類: 代表目標(biāo)類的成員變量碴卧。
- Method 類: 代表目標(biāo)類的方法。
- Constructor 類: 代表目標(biāo)類的構(gòu)造方法维贺。
- Array 類: 提供了動(dòng)態(tài)創(chuàng)建數(shù)組就乓,以及訪問(wèn)數(shù)組的元素的靜態(tài)方法妓柜。
Class 類
? 在程序運(yùn)行期間澳泵,Java運(yùn)行時(shí)系統(tǒng)始終為所有的對(duì)象維護(hù)一個(gè)被稱為運(yùn)行時(shí)的類型表示玄柏。這個(gè)信息跟蹤著每個(gè)對(duì)象所屬的類。虛擬機(jī)利用運(yùn)行時(shí)類型信息選擇相應(yīng)的方法執(zhí)行满败。
? 然而窘奏,可以通過(guò)專門(mén)的Java類訪問(wèn)這些信息。保存這些信息的類被成為Class葫录,這個(gè)名字很容易讓人混淆着裹。Object 類中的getClass() 方法將返回一個(gè)Class類型的實(shí)例。
獲取Class對(duì)象的三種方法
- 如果類在一個(gè)包里,包的名字也作為做類名的一部分骇扇。
Random generator = new Random();
Class cl = generator.getClass();
System.out.println(cl.getName());//java.util.Random
-
如果類名保存字符串中摔竿,并可在運(yùn)行時(shí)該變,即可使用這種方法少孝。forName() 方法會(huì)爆ClassNotFoundException 異常继低,所以需要進(jìn)行異常處理。
Class.forName() 內(nèi)部通過(guò)反射API根據(jù)目標(biāo)類名將類手動(dòng)加載到內(nèi)存中稍走,稱為類加載器加載方法袁翁。加載過(guò)程中會(huì)把目標(biāo)類的static方法,變量婿脸,代碼塊加載到JVM粱胜,注意此時(shí)尚未創(chuàng)建對(duì)象實(shí)例
String className = "java.util.Random";
Class cl = class.forName(className);
- 如果T是任意的Java類型(或void 關(guān)鍵字),T.class 將代表匹配的類對(duì)象
Class cl = Random.class;
獲取構(gòu)造器--Constructor 類
-
Constructor[] getConstructors()
:獲得所有public構(gòu)造器狐树; -
Constructor[] getDeclaredConstructors()
:獲得所有訪問(wèn)權(quán)限的構(gòu)造器 -
Constructor getConstructor(Class[] params)
:根據(jù)指定參數(shù)獲得對(duì)應(yīng)構(gòu)造器焙压; -
Constructor getDeclaredConstructor(Class[] params)
:根據(jù)指定參數(shù)獲得對(duì)應(yīng)構(gòu)造器;
獲得方法--Method 類
-
Method[] getMethods()
:獲得所有public方法抑钟; -
Method[] getDeclaredMethods()
:獲得所有訪問(wèn)權(quán)限的方法涯曲; -
Method getMethod(String name, Class[] params)
:根據(jù)方法簽名獲取類自身對(duì)應(yīng)public方法,或者從基類繼承和接口實(shí)現(xiàn)的對(duì)應(yīng)public方法在塔; -
Method getDeclaredMethod(String name, Class[] params)
:根據(jù)方法簽名獲得對(duì)應(yīng)的類自身聲明方法幻件,訪問(wèn)權(quán)限不限;
獲得變量--Field 類
-
Field[] getFields()
:獲得類中所有public變量 -
Field[] getDeclaredFields()
:獲得類中所有訪問(wèn)權(quán)限變量 -
Field getField(String name)
:根據(jù)變量名得到對(duì)應(yīng)的public變量 -
Field getDeclaredField(String name)
:根據(jù)變量名獲得對(duì)應(yīng)的變量蛔溃,訪問(wèn)權(quán)限不限傲武;
實(shí)戰(zhàn)
我們來(lái)個(gè)例子加深一下印象。
打印一個(gè)類的所有構(gòu)造函數(shù)
public static void printConstructors(Class cl)
{
//返回包含Constructor 對(duì)象的數(shù)組城榛,其中包含了Class對(duì)象的所有構(gòu)造器
Constructor[] constructors = cl.getDeclaredConstructors();
for (Constructor c: constructors) {
//String getName()
//返回一個(gè)用于描述構(gòu)造器揪利、方法或域名的字符串
String name = c.getName();
System.out.print(" ");
String modifiers = Modifier.toString(c.getModifiers());
if (modifiers.length()>0)
System.out.print(modifiers+ " ");
System.out.print(name+"(");
//Class[] getParameterTypes() (在Constructor 和 Method 類中)
//返回一個(gè)用于描述參數(shù)類型的Class對(duì)象數(shù)組
printParameterType(c.getParameterTypes());
System.out.println(");");
}
}
打印一個(gè)類的所有方法
public static void printMethods(Class cl)
{
//返回包含Method 對(duì)象的數(shù)組,返回這個(gè)類或接口的全部方法狠持,但不包括由超類繼承了的方法
Method[] methods = cl.getDeclaredMethods();
for (Method m:methods) {
//Class getReturnType() (在 Method 類中)
//返回一個(gè)用于描述返回類型的Class對(duì)象
Class retType = m.getReturnType();
String name = m.getName();
System.out.print(" ");
//打印修飾符疟位、返回類型和方法名稱
String modifiers =Modifier.toString(m.getModifiers());
if (modifiers.length()>0)
System.out.print(modifiers+" ");
System.out.print(retType.getName()+" "+ name + "(");
printParameterType(m.getParameterTypes());
System.out.println(");");
}
}
打印一個(gè)類的所有字段
public static void printFields(Class cl)
{
//Field[] getDeclaredFields()
//返回包含F(xiàn)ield 對(duì)象的數(shù)組,這些對(duì)象記錄了這個(gè)類的全部域
Field[] fields = cl.getDeclaredFields();
for (Field f : fields){
Class type = f.getType();
String name = f.getName();
System.out.print(" ");
String modifiers = Modifier.toString(f.getModifiers());
if (modifiers.length()>0)
System.out.print(modifiers+" ");
System.out.println(type.getName()+" "+ name+ ";");
}
}
打印方法的參數(shù)類型
public static void printParameterType(Class[] paramTypes)
{
for (int j = 0;j<paramTypes.length;j++) {
if (j>0)
System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
}
測(cè)試
public static void main(String[] args)
{
String name;
if (args.length>0)
name = args[0];
else {
Scanner in = new Scanner(System.in);
System.out.println("Enter class name(e.g java.util.Date): ");
name = in.next();
}
try {
//print class name and superclass name (if != object)
//調(diào)用Class 的靜態(tài)方法 forName 獲得類名對(duì)應(yīng)的Class 對(duì)象
Class cl = Class.forName(name);
//獲取父類所對(duì)應(yīng)的Class 對(duì)象
Class supercl = cl.getSuperclass();
//返回對(duì)應(yīng)modifiers 中位設(shè)置的修飾符的字符串表示
String modifiers = Modifier.toString(cl.getModifiers());
if (modifiers.length()>0)
System.out.print(modifiers+" ");
System.out.print("class "+ name);
//判斷是否有繼承父類
if (supercl != null && supercl != Object.class)
System.out.print(" extends "+ supercl.getName());
System.out.print("\n{\n");
printConstructors(cl);
System.out.println();
printMethods(cl);
System.out.println();
printFields(cl);
System.out.println("}");
}catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
System.exit(0);
}