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[] args為null;
④若原方法宣告為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、Method和Field、 Constructor物件都有setAccessible()方法。
2、setAccessible啟動和禁用訪問安全檢查的開關。
3、引數值為true則指示反射的物件在使用時應該取消Java語言訪問檢查。
① 提高反射的效率。 如果程式碼中必須用反射, 而該句程式碼需要頻繁的被呼叫, 那麼請設定為true。
②使得原本無法訪問的私有成員也可以訪問;
4、引數值為false則指示反射的物件應該實施Java語言訪問檢查。