反射技術其實就是動態加載一個指定的類,並獲取該類中的所有內容。而且將字節碼文件封裝成對象,並將字節碼文件中的內容都封裝成對象,這樣便於操作這些成員,簡單來說:反射技術可以對一個類進行解剖,反射大大增強了應用程序的可擴展性。
反射技術的原理如下圖所示:

但是要想要對字節碼文件進行解剖,必須要有字節碼文件對象. 如何獲取字節碼文件對象呢?
要讀取的類文件源碼:
1 package Reflect; 2 3 public class Person { 4 5 /** 6 * @param args 7 */ 8 private String name; 9 private int age; 10 public Person(){ 11 System.out.println("Construcor run.."); 12 } 13 public Person(String name,int age){ 14 this.name=name; 15 this.age=age; 16 System.out.println("Person param run..."); 17 } 18 public static void method(){ 19 System.out.println("method run..."); 20 } 21 public static void paramMethod(String name,int age){ 22 System.out.println("name="+name+"age:"+age); 23 } 24 public static void staticMethod(){ 25 System.out.println("static run"); 26 } 27 public void show(){ 28 System.out.println(name+"Method show run.."+age); 29 } 30 31 }
獲取字節碼文件對象有三種方式:
(1)
/*
* 獲取字節碼對象的方式:
* 1,Object類中的getClass()方法的。
* 想要用這種方式,必須要明確具體的類,並創建對象。
* 麻煩
*/
1 public static void getObject_1() { 2 Person p=new Person(); 3 Class<? extends Person> classz=p.getClass(); 4 System.out.println(classz); 5 Person p1=new Person(); 6 Class<? extends Person> classz1=p.getClass(); 7 System.out.println(classz1); 8 System.out.println(classz==classz1); 9 }
(2)
/*
* 方式二:
* 任何數據類型(基本數據類型和引用數據類型)都具備一個靜態的屬性.class來獲取其對應的Class對象。
* 相對簡單,但是還是要明確用到類中的靜態成員。
* 還是不夠擴展。
*
*/
1 public static void getObject_2() { 2 3 Class classz=Person.class; 4 Class classz1=Person.class; 5 System.out.println(classz==classz1); 6 }
(3)
/*
* 方式三:
* 只要通過給定的類的 字符串名稱就可以獲取該類,更為擴展。
* 可是用Class類中的方法完成。
* 該方法就是forName.
* 這種方式只要有名稱即可,更為方便,擴展性更強。
*/
1 public static void getObject_3() throws ClassNotFoundException { 2 String classname="Reflect.Person"; 3 Class classz=Class.forName(classname); 4 System.out.println(classz); 5 }
獲取Class中的構造函數初始化對象:
(1)調用空參數的構造函數:使用Class類中的newInstance()方法
//早期:new時候,先根據被new的類的名稱找尋該類的字節碼文件,並加載進內存,
// 並創建該字節碼文件對象,並接着創建該字節文件的對應的Person對象.
1 //現在: 2 String name = "cn.itcast.bean.Person"; 3 //找尋該名稱類文件,並加載進內存,並產生Class對象。 4 Class clazz = Class.forName(name); 5 //如何產生該類的對象呢? 6 Object obj = clazz.newInstance();
(2)調用帶參數的構造函數:先要獲取指定參數列表的構造函數對象,然后通過該構造函數的對象的newInstance(實際參數)進行對象的初始化
/* * 當獲取指定名稱對應類中的所體現的對象時, * 而該對象初始化不使用空參數構造該怎么辦呢? * 既然是通過指定的構造 函數進行對象的初始化, * 所以應該先獲取到該構造函數。 通過字節碼文件對象即可完成。 * 該方法是:getConstructor(paramterTypes); * */
1 //帶參數初始化新創建的對象 2 public static void createNewObject_param() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { 3 String classname="Reflect.Person"; 4 Class classz=Class.forName(classname); 5 Constructor constructor=classz.getConstructor(String.class,int.class); 6 constructor.newInstance("Java",30); 7 }
獲取反射類的字段:
1 public static void getFiledDemo() throws ClassNotFoundException, 2 NoSuchFieldException, SecurityException, InstantiationException, 3 IllegalAccessException { 4 Class classz = Class.forName("Reflect.Person"); 5 Field field = null; 6 field = classz.getDeclaredField("age"); 7 field.setAccessible(true); 8 Object obj = classz.newInstance(); 9 field.set(obj, 89); 10 Object o = field.get(obj); 11 System.out.println(o); 12 }
獲取反射類的成員方法:
(1)獲取空參數一般方法
1 private static void getMethodDemo_2() throws Exception { 2 Class clazz = Class.forName("Reflect.Person"); 3 4 Method method = clazz.getMethod("show", null);// 獲取空參數一般方法。 5 6 // Object obj = clazz.newInstance(); 7 Constructor constructor = clazz.getConstructor(String.class, int.class); 8 Object obj = constructor.newInstance("linux", 37); 9 10 method.invoke(obj, null); 11 }
(2)獲取帶參數的一般方法
1 private static void getMethodDemo_3() throws Exception { 2 3 Class clazz = Class.forName("Reflect.Person"); 4 5 Method method = clazz.getMethod("paramMethod", String.class, int.class); 6 7 Object obj = clazz.newInstance(); 8 9 method.invoke(obj, "Ruby", 89); 10 }
(3)獲取反射類的公有、私有方法
1 private static void getMethodDemo() throws ClassNotFoundException { 2 Class classz = Class.forName("Reflect.Person"); 3 Method[] methods = classz.getMethods();// 獲取反射類中所有共有的方法 4 methods = classz.getDeclaredMethods();// 獲取本類中包括私有的所有的方法 5 for (Method method : methods) { 6 System.out.println(method); 7 } 8 }
本文為博主原創文章,轉載請注明出處:http://www.cnblogs.com/ysw-go/
1、本博客的原創原創文章,都是本人平時學習所做的筆記,如有錯誤,歡迎指正。
2、如有侵犯您的知識產權和版權問題,請通知本人,本人會即時做出處理文章。
3、本博客的目的是知識交流所用,轉載自其它博客或網站,作為自己的參考資料的,感謝這些文章的原創人員
