利用反射构造对象

这里先补充一个概念:类的反射

在程序运行的时候,查看一个类里面有哪些信息(包含的数据成员和方法成员),这个过程称之为反射。

如果我们知道要使用哪个类,只需要用这个类来创建对象,然后就可以调用获取这个对象里面的数据和方法;相反,如果我们不知道使用哪个类,就需要使用反射获取类的信息,看里面有些什么东西,然后再使用。

下面来看一份代码:

User.java:

 

 1 package com.hw.Class0228;
 2 
 3 public class User {
 4     private int age;
 5     private String name;
 6     private double score;
 7     private int id;
 8     
 9     public User(){}
10     public User(int age,String name,double score){
11         this.age = age;
12         this.name = name;
13         this.score = score;
14     }
15     private User(int id){
16         this.id = id;
17     }
18     
19     public int getAge(){
20         return age;
21     }
22     public void setAge(int age){
23         this.age = age;
24     }
25     
26     public String getName(){
27         return name;
28     }
29     public void setName(String name){
30         this.name = name;
31     }
32     
33     public double getScore(){
34         return score;
35     }
36     public void setScore(double age){
37         this.score = score;
38     }
39     
40     public void introduce(){
41         System.out.println("大家好,我的名字是:"+getName());
42     }
43     public void show(){
44         System.out.println(id+"of"+getName()+"的分数是:"+getScore());
45     }
46 }

 

Demo01_GetClass.java:

 

 1 package com.hw.Class0228;
 2 
 3 import java.lang.reflect.Constructor;
 4 public class Demo01_GetClass {
 5     public static void main(String[] args) throws Exception {
 6         User user1 = new User(18,"小明",98);  //这里先创建两个对象
 7         User user2 = new User(20,"小红",100);
 8         
 9         Class c1 = user1.getClass(); //调用getClass()方法获取一个Class对象
10         Class c2 = user2.getClass();
11         
12         Class c4 = User.class; //通过类
13         System.out.println(c1==c4);
14         
15         Class c5 = Class.forName("com.hw.Class0228.User");  //使用这个静态方法
16         System.out.println(c1==c5);
17         
18         //得到所有的public构造方法
19 //        Constructor[] cs = c5.getConstructors();
20 //        for(Constructor con : cs){
21 //            System.out.println(con);
22 //        }
23         
24         /**
25          * 下面这种方法是得到单个(指定的)构造方法。里面传递的参数是可变参数(个数可变)
26          * 每个参数的类型都是Class类型的,所以这里还是一个Class对象
27          * 因为每一个类型都对应一个Class对象
28          * 所以当传递一组类型过去的时候,会根据这一组类型匹配对应的构造方法
29          */
30         Constructor con = c5.getConstructor(); //没有参数,就没有类型,只能匹配到无参的构造方法
31         
32         /**
33          * 这个方法就是新建实例,里面的参数也是可变参数。
34          * 又因为con是无参的构造方法,所以这里也不能传递任何参数
35          * 调用这个方法作用其实就是创建出来了一个对象,这个对象是User类型的。
36          * 但这个方法的返回值却是一个Object类型的。为啥?
37          * 因为我们自己创建的类名有各种可能,这个方法的返回值不可能能够确定,因此这里就是Object类型的
38          * 但本质上是一个Object类型的
39          */
40         Object o = con.newInstance(); 
41         User user = (User)o;  //这里开始是一个验证,验证o其实是一个Object对象
42         user.show();
43     }
44 }

 补充:get.Constructor使用来得到构造方法的。使用getConstructors(无参)可以得到所有的构造方法。这个方法返回的是一个constructors的数组。循环输出会输出里面所有public的构造方法。

而get.Constructor则是得到单个构造方法,当然这个里面的参数是可变参数。

而con.newInstance()其实就创建出来了一个User类型的对象。


 如果我们想得到私有的构造方法要怎么办?

看代码:

 1 package com.hw.Class0228;
 2 
 3 import java.lang.reflect.Constructor;
 4 public class Demo01_GetClass {
 5     public static void main(String[] args) throws Exception {
 6         User user1 = new User(18,"小明",98);  //这里先创建两个对象
 7         User user2 = new User(20,"小红",100);
 8         
 9         Class c = Class.forName("com.hw.Class0228.User");
10         Constructor[] cs = c.getDeclaredConstructors();
11         for(Constructor con : cs){
12             System.out.println(con);
13         }
14     }
15 }

 declared的意思就是声明的。就可以忽略访问权限,全部都可以得到。对应上面这个得到所有的构造方法的方法,同理就还有一个getDeclaredConstructor(),传参数进去就可。

但是啊,我们来看这样一段代码:

 1 package com.hw.Class0228;
 2 
 3 import java.lang.reflect.Constructor;
 4 public class Demo01_GetClass {
 5     public static void main(String[] args) throws Exception {
 6         User user1 = new User(18,"小明",98);  //这里先创建两个对象
 7         User user2 = new User(20,"小红",100);
 8         
 9         Class c = Class.forName("com.hw.Class0228.User");
10         Constructor con = c.getDeclaredConstructor(int.class);
11         Object o = con.newInstance(28);
12         User user = (User)o;
13         user.show();
14     }
15 }

 

直接报错了。can not access a member of class com.hw.Class0228.User with modifiers "private"

所以,因为这个构造方法是私有的,所以不能得到。但真的就不能得到了吗?非也。

加一个con.setAccessible(true);就可以了。

 1 package com.hw.Class0228;
 2 
 3 import java.lang.reflect.Constructor;
 4 public class Demo01_GetClass {
 5     public static void main(String[] args) throws Exception {
 6         User user1 = new User(18,"小明",98);  //这里先创建两个对象
 7         User user2 = new User(20,"小红",100);
 8         
 9         Class c = Class.forName("com.hw.Class0228.User");
10         Constructor con = c.getDeclaredConstructor(int.class);
11         con.setAccessible(true);
12         Object o = con.newInstance(28);
13         User user = (User)o;
14         user.show();
15     }
16 }

 

posted @ 2021-03-07 16:33  EvanTheBoy  阅读(86)  评论(0编辑  收藏  举报