java裡的反射機制

來源:互聯網
上載者:User
題外話:

下個周末世界盃就開始了,對於一個地道的球迷而言,這無疑是一個期盼以久的盛大的節日,無論從生理上還是心理上我都做好了充分的準備,準備全身心的投入到這個四年一度的節日中去,祝天下球迷朋友們節日快樂,好好享受吧!

什麼是反射機制

正像物理中的反射一樣,就像我們站在鏡子面前能看到自己的模樣。但是這裡的反射機制又有別於物理中的反射,這裡的反射機制著重強調的是“動態”。反射機制是指能在class(自己)啟動並執行情況下,看到自己主要是指程式可以訪問、檢測和修改它本身狀態或行為的一種能力。由於設計的時候加入了這種機制使得java語言具有了一定的動態能力(所謂一定的動態能力是指:java語言並不能象python,ruby那樣在程式運行時,允許改變程式結構和變數的類型,但是他可以在程式啟動並執行時候檢測自己的狀態和行為,並能修改欄位的值)。正是由於反射機制的存在,所以java語言又有別於“寫入程式碼”的c,c++,同時也正是這個機制的優勢,使得微軟在後來模仿java語言發明了c#語言,同樣c#語言也具備了這個優勢。

如何?:

java裡面所有對象都繼承於一個基本對象class object,這個對象不是我們通過程式手動寫出來的,他是在每一個class使用的時候由jvm自動產生的。這個類提供了若干個Reflection API,我們可以調用這些Reflection API來檢查class的相關方法,變數,名字,介面以及繼承…………相關資訊。而我們通過SUN提供的這些Reflection API來檢查各種各樣的class資訊的過程就是反射(下面我寫的這個例子就是做的這件事),象這種事,每天JVM都在做,任何一個時候都在不停的做,只要有一個class產生,被操作,jvm都會調用反射API去得到他的方法,屬性,變數。羅列幾個常用的API有:getName() 得到class/interface 名稱;getDeclaredMethods() 得到方法;getDeclaredFields() 得到變數……。

例子(三個例子,得到欄位,方法,名字):

以下是我使用反射機制的三個例子,分別是得到名字,方法,以及屬性和修改屬性。

例子一:

/*得到方法名字*/

Class c = null;

c = Class.forName(args[0]);

Package p;

p = c.getPackage();

if (p != null)

System.out.println("package "+p.getName()+";");

執行結果(例):

package java.util;

該例子摘自侯捷老師一書《java反射機制》“Java Reflection API 運用樣本”一節,正像我們常常問的那樣,我們在EJB裡面寫了個方法,或者引入了一個包,用戶端怎麼知道是哪一個包,是哪一個方法,就像上面一樣,JVM其實在背後做了上面這段代碼的事,然後列印了上面這個結果,也就是說JVM通過反射知道了他想知道的資訊。明白了吧,JVM就是這樣得到了這些資訊。剛開始我學習反射的時候,有一個疑問在我腦海裡困惑了很久“反射只能動態時候看自己的方法,函數,變數,又不能象動態語言那樣操作,這樣做意義何在,似乎找不到一點好處”,通過這裡,我明白了,其實反射不是給你看的,是給JVM看的,讓他或者容器(例如EJB)知道到底該得到什麼方法,什麼class。

例子二:

/*得到所有方法*/

package src;

 

import java.lang.reflect.*;

 

public class reflectiontest {   

 

    public static void main(String args[]) {

        try {           

 

            Class c = Class.forName("java.lang.String");//轉化為class object對象,可以反射。

            Method m[] = c.getDeclaredMethods();

            System.out.println(m[0].toString());

/****查看自己的所有方法******/

            for (int i = 0; i < m.length; i++)

                System.out.println(m[i].toString());

/****************************/

 

 

/****查看自己的第一個方法****/

System.out.println(m[0].toString());

/****************************/

           }

               catch (Throwable e) {

            System.err.println(e);  

            }   

 

    }

}

由於java是完全面相對象的編程,所以在java裡面string型,int型,這些常量類型也是對象化了的,我們可以把他們當作一個對象來看待和操作。通過上面的例子得到的結果是所有string的公用方法。

例子三:

/*得到屬性以及修改屬性,也就是我們常常使用的set和get方法*/

public class Test {

public double d;

public static void main(String args[])

{

Class c = Class.forName("Test");

Field f = c.getField("d"); //指定field 名稱

Test obj = new Test();

System.out.println("d= " + (Double)f.get(obj));

f.set(obj, 12.34);

System.out.println("d= " + obj.d);

}

}

該例子摘自侯捷老師一書《java反射機制》倒數第二小節“執行期變更fields 內容”,這個方法大家用得多了吧,其實裡面也包含了反射機製得原理,即使說我們通過實名把我們要操作的對象轉換成class object對象Class c = Class.forName("Test");然後通過c.getField()方法(該方法就是反射制的體現) 就可以動態(這裡所謂的動態就是指在程式在啟動並執行時候)取得自己的變數,並且修改和設定。

為什麼用reflection,他有什麼好處:

其實JNDI就是reflection的一個具體表現。舉個例:ejb裡面我們放了一個類,用戶端怎麼知道我們要使用什麼類的什麼方法,我們知道用的是jndi,其實JNDI就是反射機制的一個具體表現,Class c = Class.forName("java.lang.String");雙音號裡面是調用的函數或者方法的名字,通過名字來找到我們要調用的方法,這就是我們說的JNDI,JVM在內部執行個體化了一個class object,正如我們上面提到的這個class object裡面有很多方法,通過這些方法就可以看到他得到的那個類的所有的公用方法,並且調用相應的方法。否則用戶端也不能知道我們調用的是什麼類。

同樣我們常常使用getXXX()和setXXX()方法也是一樣的道理。

總結起來可以概括為:“動態來選擇執行的方法和變數,不是靜態寫出來。”

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.