標籤:修飾符 java對象 tail method bar 它的 特定 不容易 strong
1、反射概念以及為什麼要使用反射
我們考慮一個情境,如果我們在程式運行時,一個對象想要檢視自己所擁有的成員屬性,該如何操作?
那再考慮這樣另一個情境,如果我們想要在運行期獲得某個類Class的資訊如它的屬性、構造方法、一般方法 後再考慮是否建立它的對象,這種情況該怎麼辦呢?這就需要用到反射!
我們.Java檔案在編譯後會變成.class檔案,這就像是個鏡面,本身是.java,在鏡中是.class,他們其實是一樣的;那麼同理,我們看到鏡子的反射是.class,就能通過反編譯,瞭解到.java檔案的本來面目。即為反射。
官方給出的概念:反射是java語言的一個特性,它允程式在運行時(注意不是編譯的時候)來進行自我檢查並且對內部的成員進行操作。例如它允許一個java的類擷取它所有的成員變數和方法並且顯示出來。
2、擷取類的三種方式
[java] view plain copy
- //第一種方式:
- 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、建立對象方法
[java] view plain copy
- Class c =Class.forName("User");
-
- //建立此Class 對象所表示的類的一個新執行個體
- Object o = c.newInstance(); //調用了User的無參數構造方法.
4、擷取類屬性
a、擷取所有屬性修飾符、屬性名稱
[java] view plain copy
- //擷取整個類
- 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、擷取特定屬性並賦值
[java] view plain copy
- 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。如果不適用反射,那麼你就只能寫死到代碼裡了。
反射一般在架構中使用較多。因為架構要適用更多的情況。對靈活性要求較高。
缺點:
運用反射會使我們的軟體的效能降低,複雜度增加,所以還要我們謹慎的使用它,發生錯誤不容易檢驗,因為是在運行時候發生錯誤,不是編譯期間。
java反射機制