1. 程式人生 > >Spring IOC原理之Java反射機制

Spring IOC原理之Java反射機制

1、反射概念以及為什麼要使用反射

我們考慮一個場景,如果我們在程式執行時,一個物件想要檢視自己所擁有的成員屬性,該如何操作?

那再考慮這樣另一個場景,如果我們想要在執行期獲得某個類Class的資訊如它的屬性、構造方法、一般方法 後再考慮是否建立它的物件,這種情況該怎麼辦呢?這就需要用到反射!

我們.java檔案在編譯後會變成.class檔案,這就像是個鏡面,本身是.java,在鏡中是.class,他們其實是一樣的;那麼同理,我們看到鏡子的反射是.class,就能通過反編譯,瞭解到.java檔案的本來面目。即為反射

官方給出的概念:反射是java語言的一個特性,它允程式在執行時(注意不是編譯的時候)來進行自我檢查並且對內部的成員進行操作。例如它允許一個java的類獲取它所有的成員變數和方法並且顯示出來。

2、獲取類的三種方式

//第一種方式:  
Class c1 = Class.forName(User);  
//第二種方式:  
//java中每個型別都有class 屬性.  
Class c2 = User.class<span style="font-family: Arial, Helvetica, sans-serif;">;  </span>
//第三種方式:  
//java語言中任何一個java物件都有getClass 方法  
User u = new User();  
Class c3 = u.getClass(); //c3是執行時類 (e的執行時類是User)  
3、建立物件方法
Class c =Class.forName("User");  
  
//建立此Class 物件所表示的類的一個新例項  
Object o = c.newInstance(); //呼叫了User的無引數構造方法.  
4、獲取類屬性

a、獲取所有屬性修飾符、屬性名

//獲取整個類  
            Class c = Class.forName("java.lang.Integer");  
            //獲取所有的屬性
            Field[] fs = c.getDeclaredFields();  
       
            //定義可變長的字串,用來儲存屬性  
            StringBuffer sb = new StringBuffer();  
            //通過追加的方法,將每個屬性拼接到此字串中  
            //最外邊的public定義  
            sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n");  
            //裡邊的每一個屬性  
            for(Field field:fs){  
                sb.append("\t");//空格  
                sb.append(Modifier.toString(field.getModifiers())+" ");//獲得屬性的修飾符,例如public,static等等  
                sb.append(field.getType().getSimpleName() + " ");//屬性的型別的名字  
                sb.append(field.getName()+";\n");//屬性的名字+回車  
            }  
            sb.append("}");  
<span style="white-space:pre">	</span>  //輸出
            System.out.println(sb);  
b、獲取特定屬性並賦值
public static void main(String[] args) throws Exception{  
              
    //以前的方式:  
    /* 
    User u = new User(); 
    u.age = 12; //set 
    System.out.println(u.age); //get 
    */  
              
    //獲取類  
    Class c = Class.forName("User");  
    //獲取id屬性  
    Field idF = c.getDeclaredField("id");  
    //例項化這個類賦給o  
    Object o = c.newInstance();  
    //打破封裝  
    idF.setAccessible(true); //使用反射機制可以打破封裝性,導致了java物件的屬性不安全。  
    //給o物件的id屬性賦值"110"  
    idF.set(o, "110"); //set  
    //get  
    System.out.println(idF.get(o));  
5、獲取方法

方法關鍵字

含義

getDeclaredMethods()

獲取所有的方法

getReturnType()

獲得方法的放回型別

getParameterTypes()

獲得方法的傳入引數型別

getDeclaredMethod("方法名",引數型別.class,……)

獲得特定的方法

構造方法關鍵字

含義

getDeclaredConstructors()

獲取所有的構造方法

getDeclaredConstructor(引數型別.class,……)

獲取特定的構造方法

父類和父介面

含義

getSuperclass()

獲取某類的父類

getInterfaces()

獲取某類實現的介面


6、反射機制的作用

優點:

a、Java的反射機制就是增加程式的靈活性,避免將程式寫死到程式碼裡。
例如: 例項化一個 person()物件, 不使用反射,需要new person(); 如果想變成例項化其他類,那麼必須修改原始碼,並重新編譯。
      使用反射: class.forName("person").newInstance(); 而且這個類描述可以寫到配置檔案中,如 **.xml, 這樣如果想例項化其他類,只要修改配置檔案的"類描述"就可以了,不需要重新修改程式碼並編譯。在JavaWeb中載入資料庫驅動時會用到。
b、增加程式的靈活性。
例如:struts中。請求的派發控制。
當請求來到時。struts通過查詢配置檔案。找到該請求對應的action方法。然後通過反射例項化action。並呼叫響應method。如果不適用反射,那麼你就只能寫死到程式碼裡了。


反射一般在框架中使用較多。因為框架要適用更多的情況。對靈活性要求較高。

缺點:
運用反射會使我們的軟體的效能降低,複雜度增加,所以還要我們慎重的使用它。