帶你走進java的反射機制

Java中的反射機制

概念

​ Java反射機制指的是在Java程序運行狀態中,對於任何一個類,都可以獲得這個類的所有屬性和方法;對於給定的一個對象,都能夠調用它的任意一個屬性和方法。這種動態獲取類的內容以及動態調用對象的方法稱爲反射機制。

​ Java的反射機制允許編程人員在對類未知的情況下,獲取類相關信息的方式變得更加多樣靈活,調用類中相應方法,是Java增加其靈活性與動態性的一種機制。

反射機制的優點與缺點

​ 爲什麼要用反射機制?直接創建對象不就可以了嗎,這就涉及到了動態與靜態的概念
靜態編譯:在編譯時確定類型,綁定對象,即通過。
動態編譯:運行時確定類型,綁定對象。動態編譯最大限度發揮了java的靈活性,體現了多 態的應用,有以降低類之間的藕合性。
一句話,反射機制的優點就是可以實現動態創建對象和編譯,體現出很大的靈活性,特別是在J2EE的開發中它的靈活性就表現的十分明顯。比如,一個大型的軟件,不可能一次就把把它設計的很完美,當這個程序編譯後,發佈了,當發現需要更新某些功能時,我們不可能要用戶把以前的卸載,再重新安裝新的版本,假如這樣的話,這個軟件肯定是沒有多少人用的。採用靜態的話,需要把整個程序重新編譯一次纔可以實現功能的更新,而採用反射機制的話,它就可以不用卸載,只需要在運行時才動態的創建和編譯,就可以實現該功能。
它的缺點是對性能有影響。使用反射基本上是一種解釋操作,我們可以告訴JVM,我們希望做什麼並且它滿足我們的要求。這類操作總是慢於只直接執行相同的操作。

原理

​ 反射機制(Reflection)是Java提供的一項較爲高級的功能,它提供了一種動態功能,而此功能的體現在於通過反射機制相關的API就可以獲取任何Java類的包括屬性、方法、構造器、修飾符等信息。元素不必在JVM運行時進行確定,反射可以使得它們在運行時動態地進行創建或調用。反射技術在中間件領域應用得較多。

功能

1、獲得某個對象的屬性。

​ 實例化

2、獲得某個類的靜態屬性。

​ 首先根據類名獲得該類,同獲得某個對象的屬性一樣,通過實例化一個Field對象,接收該類聲明的屬性,不同的是,由於屬性是靜態的,所以直接從類中獲取。

3、執行某對象的方法。

​ 同樣要先獲得對象的類,然後配置類的數組,並把它作搜索方法的條件。通過getMethod()方法,得到要執行的方法。執行該invoke方法,該方法中執行的是owner對象中帶有參數args的方法。返回值是一個對象。

4、執行某個類的靜態方法。

​ 基本的原理和“執行某個類的方法”相同,不同點在於method.invoke(null,args),這裏的第一個參數是null,因爲調用的是靜態方法,所以不需要藉助owner就能運行。

5、新建類的實例。

​ 我們利用執行帶參數的構造函數的方法來新建一個實例。如果不需要參數,可以直接使用newoneClass.newlnstaneeO來實現嘲。同樣要先得到要構造的實例的類,然後構造參數的類數組,構造器是通過getConstructor(argsClass)得到的,最後使用newlnstanee(args)方法新建一個實例。

特點

​ 儘管反射機制帶來了極大的靈活性及方便性,但反射也有缺點。反射機制的功能非常強大,但不能濫用。在能不使用反射完成時,儘量不要使用,原因有以下幾點:

1、性能問題。

​ Java反射機制中包含了一些動態類型,所以Java虛擬機不能夠對這些動態代碼進行優化。因此,反射操作的效率要比正常操作效率低很多。我們應該避免在對性能要求很高的程序或經常被執行的代碼中使用反射。而且,如何使用反射決定了性能的高低。如果它作爲程序中較少運行的部分,性能將不會成爲一個問題。

2、安全限制。

​ 使用反射通常需要程序的運行沒有安全方面的限制。如果一個程序對安全性提出要求,則最好不要使用反射。

3、程序健壯性。

​ 反射允許代碼執行一些通常不被允許的操作,所以使用反射有可能會導致意想不到的後果。反射代碼破壞了Java程序結構的抽象性,所以當程序運行的平臺發生變化的時候,由於抽象的邏輯結構不能被識別,代碼產生的效果與之前會產生差異。

獲取Class對象的三種方式

1.通過類名獲取 類名.class

2.通過對象獲取 對象名.getClass()

3.通過全類名獲取 Class.forName(全類名)

複製代碼
public class ReflectionTest {
    @Test
    public void testClass() throws ClassNotFoundException {
       Class clazz = null;
       
       //1.通過類名
       clazz = Person.class;
       

       //2.通過對象名
       //這種方式是用在傳進來一個對象,卻不知道對象類型的時候使用
       Person person = new Person();
       clazz = person.getClass();
       //上面這個例子的意義不大,因爲已經知道person類型是Person類,再這樣寫就沒有必要了
       //如果傳進來是一個Object類,這種做法就是應該的
       Object obj = new Person();
       clazz = obj.getClass();
       

       //3.通過全類名(會拋出異常)
       //一般框架開發中這種用的比較多,因爲配置文件中一般配的都是全類名,通過這種方式可以得到Class實例
       String className=" com.atguigu.java.fanshe.Person";
       clazz = Class.forName(className);       
       


       
       //字符串的例子
       clazz = String.class;
       
       clazz = "javaTest".getClass();
       
       clazz = Class.forName("java.lang.String");
       
       System.out.println(); 
    }
}

總結

​ 總的來說,java反射機制是一個很好用的東西,用它可以解決很多死的東西,因爲反射機制的靈活行很大,有了他,我們就不要花太多的時間來寫操做數據庫的代碼了,而是方法更多的時間在項目的邏輯功能上,這個可以很大的減少開發時間,而且代碼的可讀性好。先在的很多開源框架都是才用的反射機制,它只要配置文件,然後按規則來調用他的方法就可以了。

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