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 }

 

posted @ 2019-05-17 16:37  sunshineBaby  阅读(4323)  评论(0编辑  收藏  举报