反射機制總結
一、 反射機制的定義-Java不是動態語言,但其有一個非常突出的動態相關機制-反射
在Java運行時環境中,對於任意一個類,能否知道這個類有哪些屬性和方法?對於任意一個對象,能否調用它的任意一個方法?答案是肯定的。這種動態獲取類的信息以及動態調用對象的方法的功能來自於JAVA語言的反射(Reflection)機制。
Reflection,這個字的意思是“反射、印象、倒影”,用在Java身上指的是我們可以於運行時加載、探知、使用編譯期間完全未知的classes。換句話說,JAVA程序可以加載一個運行時才得知名稱的class,獲悉其完整構造(但不包括methods定義),並生成其對象實體、或對其fields設值、或喚起其methods。這種”看透class”的能力(the ability the program to example itself)被稱爲introspection(內省、內觀、反省)。Reflection和introspection是常常被並提的兩個術語。
Java反射機制允許程序在運行時通過Reflection APIs取得任意一個已知名稱的class的內部信息,包括其modifiers(諸如public,static等等)、superclass(例如Object)、實現之interfaces
(例如Serializable),也包括fields和methods的所有信息,並可於運行時改變fields內容或調用methods。
注:反射機制可調用的方法也包括其定義的private類型的方法。我們知道,對於一個private類型的方法,根據封裝的機制,它是不能被外部類使用的。但是在反射機制面前,這些限制都不復存在了。換句話說,我們通過反射,可以去調用一個類的私有方法,可以去改變一個私有的成員變量(field),一切的一切都可以實現出來。這就是說通過反射機制可以打破類的包裝機制。
Java反射機制主要提供了一下功能:
(1) 在運行時判斷任意一個對象所屬的類
(2) 在運行時構造任意一個類的對象
(3) 在運行時判斷任意一個類所具有的成員變量和方法
(4) 在運行時調用任意一個對象的方法
二、在JDK中,主要由以下類來實現Java反射機制,這些類除了Class類位於java.lang包中,其餘的都位於java.lang.reflect包中
-Class 類:代表一個類
- Field類:代表類的成員變量(成員變量也稱爲類的屬性)
- Method類:代表類的方法
- Constructor類:代表類的構造方法
-- Array類:提供了動態創建數組,以及訪問數組的元素的靜態方法
注:另外還有一個java.sql.Array類,在此不討論。
三、代碼示例
1. DumpMethods類演示了ReflectionAPI的基本作用,它讀取命令行參數指定的類名,然後打印這個類的所有的方法信息。
import java.lang.reflect.Method;
/**
* 在運行時,採用反射機制動態的調用某一個對象的特定方法-示例
* @author Administrator
*
*/
public class InvokeTester {
public int add(int param1,int param2){
return param1+param2;
}
public String echo(String message){
return "hello:"+message;
}
public static void main(String[] args)throws Exception{
//傳統方式創建對象和調用成員方法
//InvokeTester test = new InvokeTester();
//System.out.println(test.add(1, 2));
//System.out.println(test.echo("tom"));
/**
* 採用反射機制創建示例對象和調用方法
* 1.首先獲取對應類的Class對象 2.再調用getMethod方法返回Method類型的方法對象
* 3.在調用Method類型的方法對象的invoke方法來實現條用Method對象所實際對應的那個方法,
* 即通過invoke可以實現對目標方法的調用
*
*/
Class<?> classtype = InvokeTester.class;
Object invokeTester = classtype.newInstance();
//System.out.println(invokeTester instanceof InvokeTester);
/**
* public Method getMethod(String name, Class<?>... parameterTypes)
* 由getMethod方法的定義可知,第一個參數爲“方法名字符串”,其餘爲可變參數(可以有至少一個參數的列表)
* 可變參數可以有兩種方法傳值,第一種是以離散的方式,第二種是以目標參數所構成的一個Clss數組的方式(如下)
*/
//Method addMethod = classtype.getMethod("add", int.class,int.class);
//Object result = addMethod.invoke(invokeTester, 1,2);
Method addMethod = classtype.getMethod("add", new Class[]{int.class,int.class});
Object result = addMethod.invoke(invokeTester, new Object[]{1,2});
System.out.println((Integer)result);
System.out.println("--------------");
Method echoMethod = classtype.getMethod("echo", new Class[]{String.class});
Object result2 = echoMethod.invoke(invokeTester, new Object[]{"Tom"});
System.out.println((String)result2);
}
}
運行結果:3
--------------
hello:Tom
------------------------------
注:類中方法用到了可變參數。
Java1.5增加了新特性:可變參數:適用於參數個數不確定,類型確定的情況,java把可變參數當做數組處理。注意:可變參數必須位於最後一項。當可變參數個數多餘一個時,必將有一個不是最後一項,所以只支持有一個可變參數。因爲參數個數不定,所以當其後邊還有相同類型參數時,java無法區分傳入的參數屬於前一個可變參數還是後邊的參數,所以只能讓可變參數位於最後一項。