Java反射,獲取類的公有、私有的構造函數(有參,無參)、方法(有參,無參)、屬性


    Class類與java.lang.reflect類庫一起對反射進行了支持,該類庫包含Field、Method和Constructor類,這些類的對象由JVM在啟動時創建,用以表示未知類里對應的成員。這樣的話就可以使用Contructor創建新的對象,用get()和set()方法獲取和修改類中與Field對象關聯的字段,用invoke()方法調用與Method對象關聯的方法。另外,還可以調用getFields()、getMethods()和getConstructors()等許多便利的方法,以返回表示字段、方法、以及構造器對象的數組,這樣,對象信息可以在運行時被完全確定下來,而在編譯時不需要知道關於類的任何事情。

    首先創建一個類

 1 public class Per {
 2      public String name="sunshine";
 3      private int age=28;
 4      public double weight=65.50;
 5      
 6      public Per(){
 7          System.out.println("測試反射獲取公有無參構造函數");
 8      }
 9      private Per(String name){
10          this.name=name;
11          System.out.println("測試反射獲取私有有參構造函數");
12      }
13      public Per(String name,int age){
14          this.name=name;
15          this.age=age;
16          System.out.println("測試反射獲取公有有多個參數構造函數name:"+name+"    age:"+age);17      }
18      public String methodT1(){
19          System.out.println("測試反射獲取公有無參方法");
20          return null;
21      }
22      public String methodT1(String name,int age){
23          System.out.println("測試反射獲取公有多個參方法");
24          System.out.println(name+":"+age);
25          return null;
26      }
27      private String methodT1(String name){
28          System.out.println("測試反射獲取私有有參方法");
29          System.out.println("name:"+name);
30          return null;
31      }
32      public String methodT2(int[] arr,String[] str){
33          System.out.println("測試反射獲取公有有數組參方法");
34          System.out.println("int[] arr:"+arr+"String[] str:"+str);
35          return null;
36      }
37      public static void main(String[] args) {
38         System.out.println("測試反射獲取main方法");
39     }
40 }

 

    1.使用java反射獲取類的構造函數(公有、私有)(有參,無參)

 

 1 import java.lang.reflect.Constructor;
 2 import java.lang.reflect.Field;
 3 import java.lang.reflect.Method;
 4 
 5 import org.junit.AfterClass;
 6 import org.junit.BeforeClass;
 7 import org.junit.Test;
 8 /**
 9  * 測試使用java反射獲取類的構造函數並創建對象
10  * @author Sunshine
11  *
12  */
13 public class ReflectPer {
14     private static Class class1;
15     //因為java反射獲取類時都需要加載類,在這里我就使用Junit的@beforeclass來去加載類,不用在每個測試方法中重復創建
16     //注:@beforeclass在執行測試方法前運行
17     @BeforeClass
18     public static void beforeClass() throws Exception{
19         System.out.println("====測試方法啟動前先加載類====");
20         class1 = Class.forName("myPractise.Per");//加載類
21     }
22     //獲取類的公有無參構造函數,並創建對象
23     @Test
24     public void test1() throws Exception{
25         Constructor constructor = class1.getConstructor(null);//獲取公有無參構造器,值為null代表獲取無參構造器
26         Per per = (Per) constructor.newInstance(null);//創建對象,返回的是Object類型要強轉
27         System.out.println(per.name);//可以調用類的屬性-----成功
28     }
29     //獲取類的公有參構造函數,並創建對象
30     @Test
31     public void test2()throws Exception{
32         Constructor constructor = class1.getConstructor(String.class,int.class);//獲取公有多個參數構造器,參數為構造器中參數的類型
33         Per per = (Per)constructor.newInstance("baby",24);//創建對象
34     }
35     //獲取類的私有有參構造函數,並創建對象
36     @Test
37     public void test3()throws Exception{
38         Constructor constructor = class1.getDeclaredConstructor(String.class);//獲取公有多個參數構造器,參數為構造器中參數的類型
39         constructor.setAccessible(true);//暴力反射,只有將屬性設置為true才可以創建對象
40         Per per = (Per)constructor.newInstance("baby");
41         System.out.println(per.weight);//可以調用類的屬性-----成功
42         //注:通常情況下一個類不可以訪問另一個類的私有的屬性,方法。。但是通過java反射可以
43     }
44     @AfterClass
45     public static void afterClass(){
46         System.out.println("===測試完成將對象賦值為null===");
47     }
48 }

   2.使用java反射獲取類的方法(公有、私有)(有參,無參)

 1 import java.lang.reflect.Constructor;
 2 import java.lang.reflect.Field;
 3 import java.lang.reflect.Method;
 4 
 5 import org.junit.AfterClass;
 6 import org.junit.BeforeClass;
 7 import org.junit.Test;
 8 /**
 9  * 測試使用java反射獲取類方法
10  * @author Sunshine
11  *
12  */
13 public class ReflectPer {
14     private static Class class1;
15     private static Per per;
16     //因為java反射獲取類時都需要加載類,在這里我就使用Junit的@beforeclass來去加載類,不用在每個方法中重復創建
17     //注:@beforeclass在執行測試方法前運行
18     @BeforeClass
19     public static void beforeClass() throws Exception{
20         System.out.println("====測試方法啟動前先加載類====");
21         class1 = Class.forName("myPractise.Per");//加載類
22         per = (Per) class1.getConstructor(null).newInstance(null);//使用反射創建對象
23     }
24     
25     //獲取類的公有無參方法
26     @Test
27     public void test4()throws Exception{
28         Method method = class1.getMethod("methodT1", null);//獲取指定的方法,參數為方法名和該方法的參數類型,因為我們這是測試無參的方法,所以傳入null
29         method.invoke(per, null);//使用invoke方法來調用,參數為指定對象,該方法傳入的參數,因為我們這是測試無參的方法,所以傳入null
30     }
31     //獲取類的公有有參方法
32     @Test
33     public void test5()throws Exception{
34         Method method = class1.getMethod("methodT1", String.class,int.class);//獲取指定的方法,參數為方法名和該方法的參數類型
35         method.invoke(per, "sunshine",25);//使用invoke方法來調用,參數為指定對象,該方法傳入的參數
36     }
37     @Test
38     public void test6()throws Exception{
39         Method method = class1.getDeclaredMethod("methodT1", String.class);//獲取指定的方法,參數為方法名和該方法的參數類型
40         method.setAccessible(true);//暴力反射,默認為false,未設置則調用類的私有方法不成功
41         method.invoke(per, "sunshine");//使用invoke方法來調用,參數為指定對象,該方法傳入的參數
42         System.out.println(method.getReturnType());//獲取到該類指定方法的返回值類型
43     }
44     @Test
45     public void test7()throws Exception{
46         Method method = class1.getMethod("methodT2", int[].class,String[].class);
47         method.invoke(per, new int[]{1,2},new String[]{"AA","BB"});
48     }
49     //獲取某個類的main方法比較特殊也可以說是只要傳入的參數為單個數組特殊
50     //jdk5之后新增特性--可變參數
51     //在加載時會將傳入的數組進行拆分,這樣就會報錯,java.lang.IllegalArgumentException: wrong number of arguments 錯誤的參數個數
52     //這時候我們可以欺騙一下虛擬機,告訴他我們傳入的是一個對象將new String[]{"AA","BB"}換成(Object)new String[]{"AA","BB"}
53     @Test
54     public void test8()throws Exception{
55         Method method = class1.getMethod("main",String[].class);
56         method.invoke(per,(Object)new String[]{"AA","BB"});
57     }
58     @AfterClass
59     public static void afterClass(){
60         System.out.println("===測試完成將對象賦值為null===");
61     }
62 }

 

3.使用java反射獲取類的屬性(公有、私有)

 1 import java.lang.reflect.Constructor;
 2 import java.lang.reflect.Field;
 3 import java.lang.reflect.Method;
 4 import java.util.Iterator;
 5 
 6 import org.junit.AfterClass;
 7 import org.junit.BeforeClass;
 8 import org.junit.Test;
 9 
10 /**
11  * 測試使用java反射獲取類的屬性
12  * 
13  * @author Sunshine
14  *
15  */
16 public class ReflectPer {
17     private static Class class1;
18     private static Per per;
19 
20     // 因為java反射獲取類時都需要加載類,在這里我就使用Junit的@beforeclass來去加載類,不用在每個測試方法中重復創建
21     // 注:@beforeclass在執行測試方法前運行
22     @BeforeClass
23     public static void beforeClass() throws Exception {
24         System.out.println("====測試方法啟動前先加載類====");
25         class1 = Class.forName("myPractise.Per");// 加載類
26         per = (Per) class1.getConstructor(null).newInstance(null);// 使用反射創建對象
27     }
28     // 公有屬性
29     @Test
30     public void test9() throws Exception {
31         // 獲取某個屬性,參數是屬性名
32         Field field = class1.getField("name");
33         // 輸出屬性值,需要傳入指定對象
34         System.out.println(field.get(per));
35         // 獲取屬性的類型
36         System.out.println(field.getType());
37         // 獲取多個屬性
38         Field[] field1 = class1.getFields();
39         // 增強for循環Jdk1.5后的新特性,只適用於數組和實現了Iterator的集合
40         for (Field str : field1) {
41             System.out.println(str);
42         }
43         // 設置屬性值
44         field.set(per, "baby");
45         System.out.println(field.get(per));
46     }
47     //私有屬性
48     @Test
49     public void test10() throws Exception {
50         Field field = class1.getDeclaredField("age");
51         field.setAccessible(true);//暴力反射
52         System.out.println(field.get(per));
53     }
54 
55     @AfterClass
56     public static void afterClass() {
57         System.out.println("===測試完成將對象賦值為null===");
58     }
59 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM