Java開發筆記(七十八)面向對象的後門——反射

做爲一門面向對象的編程語言,Java認爲一切皆是對象,每一個對象都能歸屬於某個類,甚至每一個類都可提取出一種特殊的類型,即Class類型。早在前面介紹多態的時候,就提到每一個類都存在獨一無二的基因,經過比較實例的類基因與具體類名的類基因,便可分辨某個實例是否屬於目標類。例如,若想獲取公雞類的類型,則可經過「類名.class」獲得該類的Class對象,詳細的獲取代碼以下所示:html

		// 第一種方式:經過「類名.class」獲取
		Class clsFromClass = Cock.class;
		System.out.println("clsFromClass name = " + clsFromClass.getName());

 

相對應的,若想獲取公雞實例的類型,則可經過「實例名.getClass()」獲得該實例的Class對象,詳細的獲取代碼以下所示:java

		// 第二種方式:經過「實例名.getClass()」獲取
		Cock cock = new Cock();
		Class clsFromInstance = cock.getClass();
		System.out.println("clsFromInstance name = " + clsFromInstance.getName());

 

既然Class也是一種數據類型,那麼Class對象也能調用該類型的實例方法,好比上面兩段例子代碼都調用了Class的getName方法,該方法返回的是Class對象蘊含着的目標類類名,並且是包含完整包路徑的類名。假如分別運行前面的兩段示例代碼,就會依次觀察到以下的日誌信息,從中可見getName方法確實返回了完整的類名:
clsFromClass name = com.addition.reflect.Cock
clsFromInstance name = com.addition.reflect.Cock
除了經過「類名.class」或者「實例名.getClass()」得到Class對象,甚至還能反向操做,只要提供一個保存完整類名的字符串,便可由該字符串生成目標類的Class對象,具體的獲取代碼格式形如「Class.forName("完整類名")」。經過類名字符串獲取Class對象的代碼示例以下,注意須要捕捉forName方法可能扔出的「類型未找到異常」ClassNotFoundException:編程

		// 第三種方式:經過該類的完整路徑字符串獲取
		try {
			Class clsFromString = Class.forName("com.addition.reflect.Cock");
			System.out.println("clsFromString name = " + clsFromString.getName());
		} catch (ClassNotFoundException e) { // 捕捉到類型未找到異常
			e.printStackTrace();
		}

 

上述這種經過字符串反向得到Class對象的操做被稱爲「反射」,彷彿光線照到鏡子表面反射回來那樣,看起來像是一種逆向操做。只是反射遠非逆向操做這麼簡單,它還洞悉面向對象鮮爲人知的各類奧祕,所以常常出現於一些高級的應用場合。
構成反射技術的基石主要有類型Class、字段Field、方法Method這三個好漢,其中尤以Class最爲重要,它既是從其它類中提取出來的基因類型,又是一種能夠直接訪問的普通類型。之因此說Class普通,是由於它擁有若干能夠被開發者訪問的方法,使用體驗與其它類型相比並無什麼差別。下面是Class常見的方法說明:
equals:判斷當前類型是否與目標類型相等。
getDeclaredFields:得到當前類型已聲明的全部字段(字段即屬性)。
getDeclaredField:根據指定的字段名稱得到對應的字段(字段即屬性)。
getDeclaredMethods:得到當前類型已聲明的全部方法。
getDeclaredMethod:根據指定的方法名稱以及參數類型列表得到對應的方法。
getName:獲取當前類型包括包名在內的完整類名。
getPackage:獲取當前類型所在的包名。
getSimpleName:獲取當前類型的類名(不包括包名)。
getSuperclass:獲取當前類型的父類類型。
以上的說明文字中,字段指的是Field類型,方法指的是Method類型,有關它們的詳細用法將在後面的文章中加以闡述。編程語言



更多Java技術文章參見《Java開發筆記(序)章節目錄日誌

相關文章
相關標籤/搜索