Java反射機制總結之一

反射機制總結

一、  反射機制的定義-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無法區分傳入的參數屬於前一個可變參數還是後邊的參數,所以只能讓可變參數位於最後一項。

學習參考:JAVA深度培訓視頻:第六十一講 Java反射機制深度剖析

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章