1. 程式人生 > 其它 >Java 反射機制:(十二)呼叫執行時類中指定的結構

Java 反射機制:(十二)呼叫執行時類中指定的結構

一、呼叫構造器

  1、呼叫執行時類中的指定的構造器

     ① 呼叫getDeclaredConstructor() 方法根據引數獲取指定的構造器

    ② 保證此構造器是可以訪問的(暴力反射,針對非 public 修飾)

    ③ 呼叫 newInstance() 方法建立物件

 1     @Test
 2     public void testConstructor() throws Exception {
 3         Class clazz = Person.class;
 4 
 5         //private Person(String name)
 6         /*
7 1.獲取指定的構造器 8 getDeclaredConstructor():引數:指明構造器的引數列表 9 */ 10 11 Constructor constructor = clazz.getDeclaredConstructor(String.class); 12 13 //2.保證此構造器是可訪問的 14 constructor.setAccessible(true); 15 16 //3.呼叫此構造器建立執行時類的物件 17 Person per = (Person) constructor.newInstance("Tom");
18 System.out.println(per); 19 20 }

  2、

二、呼叫屬性

  1、呼叫指定屬性

    在反射機制中,可以直接通過Field類操作類中的屬性,通過Field類提供的set()get()方法就可以完成設定和取得屬性內容的操作

public Field getField(String name) 返回此Class物件表示的類或介面的指定的public的Field。

public Field getDeclaredField(String name)返回此Class物件表示的類或介面的指定的Field。

      在 Field 中:

public Object get(Object obj) 取得指定物件obj上此Field的屬性內容

public void set(Object obj,Object value) 設定指定物件obj上此Field的屬性內容

  

  2、操作執行時類的指定的 public 的屬性

    ① 獲取執行時的類;

    ②獲取指定的屬性:要求執行時類中屬性宣告為public

    ③ 設定、獲取當前屬性的值

 1      @Test
 2      public void testField() throws Exception {
 3         Class clazz = Person.class;
 4 
 5         //建立執行時類的物件
 6         Person p = (Person) clazz.newInstance();
 7 
 8 
 9         //獲取指定的屬性:要求執行時類中屬性宣告為public
10         //通常不採用此方法
11         Field id = clazz.getField("id");
12 
13         /*
14         設定當前屬性的值
15 
16         set():引數1:指明設定哪個物件的屬性   引數2:將此屬性值設定為多少
17          */
18 
19         id.set(p,1001);
20 
21         /*
22         獲取當前屬性的值
23         get():引數1:獲取哪個物件的當前屬性值
24          */
25         int pId = (int) id.get(p);
26         System.out.println(pId);
27 
28 
29     }

  3、操作執行時類中的指定的非public修飾屬性

    ① 獲取執行時的類;

    ②獲取執行時類中指定變數名的屬性;

    ③ 保證當前屬性是可訪問的(暴力反射,防止非 public 修飾的)

    ④ 獲取、設定指定物件的此屬性值

 1     @Test
 2     public void testField2() throws Exception {
 3         Class clazz = Person.class;
 4 
 5         //建立執行時類的物件
 6         Person p = (Person) clazz.newInstance();
 7 
 8         //1. getDeclaredField(String fieldName):獲取執行時類中指定變數名的屬性
 9         Field name = clazz.getDeclaredField("name");
10 
11         //2.保證當前屬性是可訪問的
12         name.setAccessible(true);
13         //3.獲取、設定指定物件的此屬性值
14         name.set(p,"Tom");
15 
16         System.out.println(name.get(p));
17     }

三、呼叫方法

  1、操作執行時類中的指定的方法

     

Object invoke(Object obj, Object … args)

     說明:

      ①Object 對應原方法的返回值,若原方法無返回值,此時返回null;

      ②若原方法若為靜態方法,此時形參Object obj可為null;

      ③若原方法形參列表為空,則Object[] argsnull;

      ④若原方法宣告為private,則需要在呼叫此invoke()方法前,顯式呼叫方法物件的setAccessible(true)方法,將可訪問private的方法。

    操作步驟:

    ① 根據執行時類物件獲取指定的某個方法

    ② 保證當前方法是可訪問的(暴力反射,防止非 public 修飾)

    ③ 呼叫invoke() 方法

 1     @Test
 2     public void testMethod() throws Exception {
 3 
 4         Class clazz = Person.class;
 5 
 6         //建立執行時類的物件
 7         Person p = (Person) clazz.newInstance();
 8 
 9         /*
10         1.獲取指定的某個方法
11         getDeclaredMethod():引數1 :指明獲取的方法的名稱  引數2:指明獲取的方法的形參列表
12          */
13         Method show = clazz.getDeclaredMethod("show", String.class);
14         //2.保證當前方法是可訪問的
15         show.setAccessible(true);
16 
17         /*
18         3. 呼叫方法的invoke():引數1:方法的呼叫者  引數2:給方法形參賦值的實參
19         invoke()的返回值即為對應類中呼叫的方法的返回值。
20          */
21         Object returnValue = show.invoke(p,"CHN"); //String nation = p.show("CHN");
22         System.out.println(returnValue);
23 
24         System.out.println("*************如何呼叫靜態方法*****************");
25 
26         // private static void showDesc()
27 
28         Method showDesc = clazz.getDeclaredMethod("showDesc");
29         showDesc.setAccessible(true);
30         //如果呼叫的執行時類中的方法沒有返回值,則此invoke()返回null
31         //Object returnVal = showDesc.invoke(null);
32         Object returnVal = showDesc.invoke(Person.class);
33         System.out.println(returnVal);//null
34 
35     }

  2、

四、關於 setAccessible 方法

  1、MethodFieldConstructor物件都有setAccessible()方法。

  2、setAccessible啟動和禁用訪問安全檢查的開關。

  3、引數值為true則指示反射的物件在使用時應該取消Java語言訪問檢查。

    ① 提高反射的效率。 如果程式碼中必須用反射, 而該句程式碼需要頻繁的被呼叫, 那麼請設定為true

    ②使得原本無法訪問的私有成員也可以訪問;

  4、引數值為false則指示反射的物件應該實施Java語言訪問檢查。

五、