java反射(四)--反射与简单java类

一.传统简单java类
  简单的java类主要是由属性所组成,并且提供有相应的setter以及getter的处理方法,同时简单java类最大的特征就是通过对象保存相应的类的属性内容,但是如果使用传统的简单java类的开发,那么也会面临非常麻烦的困难:

 1 class Emp{
 2     private String ename;
 3     private String job;
 4
 5     public void setEname(String ename) {
 6         this.ename = ename;
 7     }
 8
 9     public void setJob(String job) {
10         this.job = job;
11     }
12
13     public String getEname() {
14         return ename;
15     }
16
17     public String getJob() {
18         return job;
19     }
20 }

--按照传统的做法,首先应该实例化Emp对象,而后通过实例化对象进行setter方法的调用来设置属性的内容:

 1 class Emp{
 2     private String ename;
 3     private String job;
 4
 5     public void setEname(String ename) {
 6         this.ename = ename;
 7     }
 8
 9     public void setJob(String job) {
10         this.job = job;
11     }
12
13     public String getEname() {
14         return ename;
15     }
16
17     public String getJob() {
18         return job;
19     }
20 }
21 public class ReflectAndJavaClassDemo {
22     public static void main(String[] args) {
23         Emp emp = new Emp();
24         emp.setEname("Mike");
25         emp.setJob("code java");
26         System.out.println("姓名: " + emp.getEname() + " 职位: " + emp.getJob());
27     }
28 }

--在整个进行Emp对象实例化并设置数据的操作过程之中,设置数据的部分是为麻烦的,可以想象如果现在Emp类中提供有50个属性,那么对于整个程序而言,将成为一大堆的setter方法的调用,即使使用构造方法赋值,也会造成很多的麻烦.或者咱们再进一步说明,在一个开发之中,简单java类的个数是非常多的,那么如果所有的简单java类都牵扯到属性赋值的问题时,我们代码的重复率会非常的高.按照传统直观的编程方式所带来的问题就是代码会存在大量的重复操作,如果要想解决对象的重复处理操作,那么唯一的解决方案就是反射机制,反射机制最大的特征就是可以根据其自身的特点(Object类直接操作属性和方法,实现相同功能类的重复操作的抽象处理).

二.属性自动设置解决方案:
  经过了分析之后已经确认了当前简单java类操作的问题所在,而对于开发者而言就需要想办法通过一种解决方案来实现属性内容的自动设置,那么这个时候的设置强烈建议采用字符串的形式来描述对应的类型:
--1.在进行程序开发的时候我们可以知道String字符串可以描述的类型由很多,并且也可以由开发者自行定义String字符串的结构,我们采用"内容|属性:内容|"的形式来为简单java类中的属性进行初始化;
--2.类设计的基本结构,应该由一个专门的工具类(ClassInstanceFactory类)负责所有的反射处理,即接收反射对象,同时可以获取指定类的实例化对象;
--3.设计的基本结构

 1 package 反射.反射与java类;
 2
 3 /**
 4  * @author : S K Y
 5  * @version :0.0.1
 6  */
 7 class Emp {
 8     private String ename;
 9     private String job;
10
11     public void setEname(String ename) {
12         this.ename = ename;
13     }
14
15     public void setJob(String job) {
16         this.job = job;
17     }
18
19     public String getEname() {
20         return ename;
21     }
22
23     public String getJob() {
24         return job;
25     }
26 }
27
28 class ClassInstanceFactory {
29     private ClassInstanceFactory() {
30     }        //构造方法私有化
31
32     /**
33      * 实例化对象创建的方法,该对象可以根据传入的字符串的结构"内容|属性:内容|"进行处理
34      *
35      * @param tClass 要进行反射实例化的Class类对象,有Class就可以反射实例化对象
36      * @param value  要设置给对象的属性内容
37      * @return  一个已经配置完内容的简单java类对象
38      */
39     public static <T> T create(Class<T> tClass, String value) {
40         return null;
41     }
42
43 }
44
45 public class ReflectAndJavaClassDemo {
46     public static void main(String[] args) {
47         //在Emp类中,存在两个String类型的成员变量ename,job,以及其相关的getter,setter
48         String value = "ename:Mike|job:code java";
49         Emp emp = ClassInstanceFactory.create(Emp.class, value);      //产生实例化对象
50     }
51 }

--这样在当前的开发之中,所需要留给用户完善的就是ClassInstanceFactory.create()方法的具体实现

三.单级属性配置
  对于此时的Emp类型里面会发现所给出的数据类型都没有其他的引用关联了,只是描述了Emp本类的对象,这样的设置我们称他为单级属性配置,所以此时应该需要处理两件事情:
--1.需要通过反射进行指定类对象的实例化处理;
--2.进行内容的设置(Field属性类型,方法名称,要设置的内容)

  1 package 反射.反射与java类;
  2
  3 import java.lang.reflect.Field;
  4 import java.lang.reflect.Method;
  5
  6 /**
  7  * @author : S K Y
  8  * @version :0.0.1
  9  */
 10 class Emp {
 11     private String ename;
 12     private String job;
 13
 14     public void setEname(String ename) {
 15         this.ename = ename;
 16     }
 17
 18     public void setJob(String job) {
 19         this.job = job;
 20     }
 21
 22     public String getEname() {
 23         return ename;
 24     }
 25
 26     public String getJob() {
 27         return job;
 28     }
 29 }
 30
 31 class ClassInstanceFactory {
 32     private ClassInstanceFactory() {
 33     }        //构造方法私有化
 34
 35     /**
 36      * 实例化对象创建的方法,该对象可以根据传入的字符串的结构"内容|属性:内容|"进行处理
 37      *
 38      * @param tClass 要进行反射实例化的Class类对象,有Class就可以反射实例化对象
 39      * @param value  要设置给对象的属性内容
 40      * @return 一个已经配置完内容的简单java类对象
 41      */
 42     public static <T> T create(Class<T> tClass, String value) {
 43         //如果想采用反射进行简单Java类对象的属性设置的时候,类中必须要有无参构造
 44         try {
 45             Object o = tClass.newInstance();
 46             BeanUtils.setValue(o, value);        //通过反射设置属性
 47             return tClass.cast(o);    //获取对象
 48         } catch (Exception e) {
 49             e.printStackTrace();        //此时如果出现异常,将异常抛出也没有多大作用
 50             return null;
 51         }
 52
 53
 54     }
 55
 56 }
 57
 58 class BeanUtils {    //进行Bean处理的工具类
 59     private BeanUtils() {
 60     }
 61
 62     /**
 63      * 实现指定对象的属性设置
 64      *
 65      * @param obj   要进行反射操作的实例化对象
 66      * @param value 包含有指定内容的字符串
 67      */
 68     public static void setValue(Object obj, String value) {
 69         String results[] = value.split("\\|");//按照竖线进行每一组属性的拆分
 70         for (int i = 0; i < results.length; i++) {  //循环设置属性内容
 71             String attval[] = results[i].split(":");   //获取属性名称及内容
 72             try {
 73                 Field field = obj.getClass().getDeclaredField(attval[0]);
 74                 Method setMethod = obj.getClass()
 75                         .getDeclaredMethod("set" + StringUtils.initcap(attval[0]), field.getType());
 76                 setMethod.invoke(obj,attval[1]);        //使用setter方法进行内容的赋值
 77             } catch (Exception e) { //捕获异常,否则的话一个属性不存在将会导致所有的属性都无法正常赋值
 78             }
 79
 80         }
 81     }
 82 }
 83
 84 class StringUtils {
 85     private StringUtils() {
 86     }
 87
 88     public static String initcap(String str) {
 89         if (str == null || str.equals("")) {
 90             return str;
 91         }
 92         if (str.length() == 1) {
 93             return str.toUpperCase();
 94         } else {
 95             return str.substring(0, 1).toUpperCase() + str.substring(1);
 96         }
 97     }
 98
 99 }
100
101 public class ReflectAndJavaClassDemo {
102     public static void main(String[] args) {
103         //在Emp类中,存在两个String类型的成员变量ename,job,以及其相关的getter,setter
104         String value = "ename:Mike|job:code java";
105         Emp emp = ClassInstanceFactory.create(Emp.class, value);      //产生实例化对象
106         System.out.println("姓名: " + emp.getEname() + " 职位: " + emp.getJob());
107     }
108 }

--运行结果

姓名: Mike 职位: code java

Process finished with exit code 0

--ClassInstanceFactory负责实例化对象并且调用BeanUtils类实现属性代码的设置,此时即便类中的属性再多,那么也可以轻松的实现setter的调用,轻松实现类对象实例化处理

四.设置多种数据类型
  虽然上述代码可以实现对于属性的配置,但是我们仍然需要考虑一个实际的情况,当前所给定的数据类型只能是String,但是在实际的开发之中,面对简单java类中的属性类型一般的可选为:Long(long),Integer(int),Double(double),String,Date(日期,日期时间),所以这个时候对于当前的程序代码就必须做出修改,要求可以实现各种数据类型的配置.
--既然要求可以实现不同类型的内容设置,并且BeanUtils类主要是完成属性赋值处理的,那么就可以在这个类之中追加有一些列的处理方法:

  1 package 反射.反射与java类;
  2
  3 import java.lang.reflect.Field;
  4 import java.lang.reflect.Method;
  5 import java.text.ParseException;
  6 import java.text.SimpleDateFormat;
  7 import java.util.Date;
  8
  9 /**
 10  * @author : S K Y
 11  * @version :0.0.1
 12  */
 13 class Emp {
 14     private long empo;
 15     private String ename;
 16     private String job;
 17     private double salary;
 18     private Date hireDate;
 19
 20     public void setEname(String ename) {
 21         this.ename = ename;
 22     }
 23
 24     public void setJob(String job) {
 25         this.job = job;
 26     }
 27
 28     public String getEname() {
 29         return ename;
 30     }
 31
 32     public String getJob() {
 33         return job;
 34     }
 35
 36     public long getEmpo() {
 37         return empo;
 38     }
 39
 40     public void setEmpo(long empo) {
 41         this.empo = empo;
 42     }
 43
 44     public double getSalary() {
 45         return salary;
 46     }
 47
 48     public void setSalary(double salary) {
 49         this.salary = salary;
 50     }
 51
 52     public Date getHireDate() {
 53         return hireDate;
 54     }
 55
 56     public void setHireDate(Date hireDate) {
 57         this.hireDate = hireDate;
 58     }
 59
 60     @Override
 61     public String toString() {
 62         return "Emp{" +
 63                 "empo=" + empo +
 64                 ", ename=‘" + ename + ‘\‘‘ +
 65                 ", job=‘" + job + ‘\‘‘ +
 66                 ", salary=" + salary +
 67                 ", hireDate=" + hireDate +
 68                 ‘}‘;
 69     }
 70 }
 71
 72 class ClassInstanceFactory {
 73     private ClassInstanceFactory() {
 74     }        //构造方法私有化
 75
 76     /**
 77      * 实例化对象创建的方法,该对象可以根据传入的字符串的结构"内容|属性:内容|"进行处理
 78      *
 79      * @param tClass 要进行反射实例化的Class类对象,有Class就可以反射实例化对象
 80      * @param value  要设置给对象的属性内容
 81      * @return 一个已经配置完内容的简单java类对象
 82      */
 83     public static <T> T create(Class<T> tClass, String value) {
 84         //如果想采用反射进行简单Java类对象的属性设置的时候,类中必须要有无参构造
 85         try {
 86             Object o = tClass.newInstance();
 87             BeanUtils.setValue(o, value);        //通过反射设置属性
 88             return tClass.cast(o);    //获取对象
 89         } catch (Exception e) {
 90             e.printStackTrace();        //此时如果出现异常,将异常抛出也没有多大作用
 91             return null;
 92         }
 93
 94
 95     }
 96
 97 }
 98
 99 class BeanUtils {    //进行Bean处理的工具类
100     private BeanUtils() {
101     }
102
103     /**
104      * 实现指定对象的属性设置
105      *
106      * @param obj   要进行反射操作的实例化对象
107      * @param value 包含有指定内容的字符串
108      */
109     public static void setValue(Object obj, String value) {
110         String results[] = value.split("\\|");//按照竖线进行每一组属性的拆分
111         for (int i = 0; i < results.length; i++) {  //循环设置属性内容
112             String attval[] = results[i].split(":");   //获取属性名称及内容
113             try {
114                 Field field = obj.getClass().getDeclaredField(attval[0]);
115                 Method setMethod = obj.getClass()
116                         .getDeclaredMethod("set" + StringUtils.initcap(attval[0]), field.getType());
117                 Object val = BeanUtils.getAttributeValue(field.getType().getName(), attval[1]);
118                 setMethod.invoke(obj, val);        //使用setter方法进行内容的赋值
119             } catch (Exception e) { //捕获异常,否则的话一个属性不存在将会导致所有的属性都无法正常赋值
120             }
121
122         }
123     }
124
125     /**
126      * 实现属性类型转化处理
127      *
128      * @param type  属性类型,通过Field获取
129      * @param value 属性的内容,传入的都是字符串,需要将其转化为指定的类型
130      * @return 转化后的数据
131      */
132     private static Object getAttributeValue(String type, String value) {
133         if ("long".equals(type) || "java.lang.Long".equals(type)) {   //长整型
134             return Long.parseLong(value);
135         } else if ("int".equals(type) || "java.lang.Integer".equals(type)) {
136             return Integer.valueOf(value);
137         } else if ("double".equals(type) || "java.lang.Double".equals(type)) {
138             return Double.valueOf(value);
139         } else if ("java.util.Date".equals(type)) {
140             SimpleDateFormat dateFormat = null;
141             if (value.matches("\\d{4}-\\d{2}-\\d{2}")) { //日期类型
142                 dateFormat = new SimpleDateFormat("yyyy-MM-dd");
143             } else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {   //日期时间
144                 dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
145             } else {
146                 return new Date();  //当前日期
147             }
148             try {
149                 return dateFormat.parse(value);
150             } catch (ParseException e) {
151                 return new Date();
152             }
153         } else {
154             return value;
155         }
156     }
157 }
158
159 class StringUtils {
160     private StringUtils() {
161     }
162
163     public static String initcap(String str) {
164         if (str == null || str.equals("")) {
165             return str;
166         }
167         if (str.length() == 1) {
168             return str.toUpperCase();
169         } else {
170             return str.substring(0, 1).toUpperCase() + str.substring(1);
171         }
172     }
173
174 }
175
176 public class ReflectAndJavaClassDemo {
177     public static void main(String[] args) {
178         //在Emp类中,存在两个String类型的成员变量ename,job,以及其相关的getter,setter
179         String value = "ename:Mike|job:code java|empo:1258|salary:750|hireDate:1911-12-12";
180         Emp emp = ClassInstanceFactory.create(Emp.class, value);      //产生实例化对象
181         System.out.println(emp);
182     }
183 }

--运行结果

Emp{empo=1258, ename=‘Mike‘, job=‘code java‘, salary=750.0, hireDate=Tue Dec 12 00:00:00 CST 1911}

Process finished with exit code 0

--此时只是列举出了常用的几种数据类型,当然如果想将其作为一个产品推广,那就必须要考虑所有可能出现的数据类型,同时可能出现的日期格式也需要考虑

五.级联对象实例化
  如果说现在给定的类对象之中存在有其他的引用的级联关系的情况下,成为多级设置,例如:一个雇员属于一个部门,一个部门属于一个公司,所以这个时候对于简单Java类的定义如下:

  1 class Company {
  2     private String name;
  3     private Date createDate;
  4
  5     public String getName() {
  6         return name;
  7     }
  8
  9     public void setName(String name) {
 10         this.name = name;
 11     }
 12
 13     public Date getCreateDate() {
 14         return createDate;
 15     }
 16
 17     public void setCreateDate(Date createDate) {
 18         this.createDate = createDate;
 19     }
 20 }
 21
 22 class Dept {
 23     private String dname;
 24     private String loc;
 25     private Company company;
 26
 27     public String getDname() {
 28         return dname;
 29     }
 30
 31     public void setDname(String dname) {
 32         this.dname = dname;
 33     }
 34
 35     public String getLoc() {
 36         return loc;
 37     }
 38
 39     public void setLoc(String loc) {
 40         this.loc = loc;
 41     }
 42
 43     public Company getCompany() {
 44         return company;
 45     }
 46
 47     public void setCompany(Company company) {
 48         this.company = company;
 49     }
 50 }
 51
 52 class Emp {
 53     private long empo;
 54     private String ename;
 55     private String job;
 56     private double salary;
 57     private Date hireDate;
 58     private Dept dept;
 59
 60     public Dept getDept() {
 61         return dept;
 62     }
 63
 64     public void setDept(Dept dept) {
 65         this.dept = dept;
 66     }
 67
 68     public void setEname(String ename) {
 69         this.ename = ename;
 70     }
 71
 72     public void setJob(String job) {
 73         this.job = job;
 74     }
 75
 76     public String getEname() {
 77         return ename;
 78     }
 79
 80     public String getJob() {
 81         return job;
 82     }
 83
 84     public long getEmpo() {
 85         return empo;
 86     }
 87
 88     public void setEmpo(long empo) {
 89         this.empo = empo;
 90     }
 91
 92     public double getSalary() {
 93         return salary;
 94     }
 95
 96     public void setSalary(double salary) {
 97         this.salary = salary;
 98     }
 99
100     public Date getHireDate() {
101         return hireDate;
102     }
103
104     public void setHireDate(Date hireDate) {
105         this.hireDate = hireDate;
106     }
107
108     @Override
109     public String toString() {
110         return "Emp{" +
111                 "empo=" + empo +
112                 ", ename=‘" + ename + ‘\‘‘ +
113                 ", job=‘" + job + ‘\‘‘ +
114                 ", salary=" + salary +
115                 ", hireDate=" + hireDate +
116                 ‘}‘;
117     }
118 }

--如果要通过Emp进行操作,则应该按照使用"."作为级联关系的处理,例: dept.dname,dept.loc,company.name,company.createDate
  dept.dname:财务部  Emp类实例对象.getDept().setDname("财务部");
--考虑可以通过级联的配置,实现类中属性的实例化: String value ="ename:Mike|job:code java|empo:1258|salary:750|hireDate:1911-12-12|dept.dname:财务部" +"|dept.company.name:一个写java的公司";现在的属性存在多级关系,那么对于多级的关系就必须与单级的配置区分开

  1 package 反射.反射与java类;
  2
  3 import java.lang.reflect.Field;
  4 import java.lang.reflect.Method;
  5 import java.text.ParseException;
  6 import java.text.SimpleDateFormat;
  7 import java.util.Arrays;
  8 import java.util.Date;
  9
 10 /**
 11  * @author : S K Y
 12  * @version :0.0.1
 13  */
 14 class Company {
 15     private String name;
 16     private Date createDate;
 17
 18     public String getName() {
 19         return name;
 20     }
 21
 22     public void setName(String name) {
 23         this.name = name;
 24     }
 25
 26     public Date getCreateDate() {
 27         return createDate;
 28     }
 29
 30     public void setCreateDate(Date createDate) {
 31         this.createDate = createDate;
 32     }
 33 }
 34
 35 class Dept {
 36     private String dname;
 37     private String loc;
 38     private Company company;
 39
 40     public String getDname() {
 41         return dname;
 42     }
 43
 44     public void setDname(String dname) {
 45         this.dname = dname;
 46     }
 47
 48     public String getLoc() {
 49         return loc;
 50     }
 51
 52     public void setLoc(String loc) {
 53         this.loc = loc;
 54     }
 55
 56     public Company getCompany() {
 57         return company;
 58     }
 59
 60     public void setCompany(Company company) {
 61         this.company = company;
 62     }
 63 }
 64
 65 class Emp {
 66     private long empo;
 67     private String ename;
 68     private String job;
 69     private double salary;
 70     private Date hireDate;
 71     private Dept dept;
 72
 73     public Dept getDept() {
 74         return dept;
 75     }
 76
 77     public void setDept(Dept dept) {
 78         this.dept = dept;
 79     }
 80
 81     public void setEname(String ename) {
 82         this.ename = ename;
 83     }
 84
 85     public void setJob(String job) {
 86         this.job = job;
 87     }
 88
 89     public String getEname() {
 90         return ename;
 91     }
 92
 93     public String getJob() {
 94         return job;
 95     }
 96
 97     public long getEmpo() {
 98         return empo;
 99     }
100
101     public void setEmpo(long empo) {
102         this.empo = empo;
103     }
104
105     public double getSalary() {
106         return salary;
107     }
108
109     public void setSalary(double salary) {
110         this.salary = salary;
111     }
112
113     public Date getHireDate() {
114         return hireDate;
115     }
116
117     public void setHireDate(Date hireDate) {
118         this.hireDate = hireDate;
119     }
120
121     @Override
122     public String toString() {
123         return "Emp{" +
124                 "empo=" + empo +
125                 ", ename=‘" + ename + ‘\‘‘ +
126                 ", job=‘" + job + ‘\‘‘ +
127                 ", salary=" + salary +
128                 ", hireDate=" + hireDate +
129                 ‘}‘;
130     }
131 }
132
133 class ClassInstanceFactory {
134     private ClassInstanceFactory() {
135     }        //构造方法私有化
136
137     /**
138      * 实例化对象创建的方法,该对象可以根据传入的字符串的结构"内容|属性:内容|"进行处理
139      *
140      * @param tClass 要进行反射实例化的Class类对象,有Class就可以反射实例化对象
141      * @param value  要设置给对象的属性内容
142      * @return 一个已经配置完内容的简单java类对象
143      */
144     public static <T> T create(Class<T> tClass, String value) {
145         //如果想采用反射进行简单Java类对象的属性设置的时候,类中必须要有无参构造
146         try {
147             Object o = tClass.newInstance();
148             BeanUtils.setValue(o, value);        //通过反射设置属性
149             return tClass.cast(o);    //获取对象
150         } catch (Exception e) {
151             e.printStackTrace();        //此时如果出现异常,将异常抛出也没有多大作用
152             return null;
153         }
154
155
156     }
157
158 }
159
160 class BeanUtils {    //进行Bean处理的工具类
161     private BeanUtils() {
162     }
163
164     /**
165      * 实现指定对象的属性设置
166      *
167      * @param obj   要进行反射操作的实例化对象
168      * @param value 包含有指定内容的字符串
169      */
170     public static void setValue(Object obj, String value) {
171         String results[] = value.split("\\|");//按照竖线进行每一组属性的拆分
172         for (int i = 0; i < results.length; i++) {  //循环设置属性内容
173             String attval[] = results[i].split(":");   //获取属性名称及内容
174             try {
175                 Object currentObject = obj;
176                 if (attval[0].contains(".")) {        //这是多级配置
177                     String temp[] = attval[0].split("\\.");
178                     //最后一位肯定是指定类中的属性名称,因此不在实例化处理的范畴之内
179                     for (int j = 0; j < temp.length - 1; j++) {  //实例化
180                         //调用相应的getter方法,如果getter方法返回了空表示该对象为实例化
181                         Method getMethod = currentObject.getClass().getDeclaredMethod(
182                                 "get" + StringUtils.initcap(temp[j]));
183                         if (getMethod.invoke(currentObject) == null) {  //该对象现在并没有被实例化
184                             Field field = currentObject.getClass().getDeclaredField(temp[j]);
185                             Method method = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[j]), field.getType());
186                             Object newObject = field.getType().getDeclaredConstructor().newInstance();
187                             method.invoke(currentObject, newObject);
188                             currentObject = newObject;
189                         } else {
190                             currentObject = getMethod.invoke(currentObject);
191                         }
192                     }
193                 } else {
194                     Field field = obj.getClass().getDeclaredField(attval[0]);
195                     Method setMethod = obj.getClass()
196                             .getDeclaredMethod("set" + StringUtils.initcap(attval[0]), field.getType());
197                     Object val = BeanUtils.getAttributeValue(field.getType().getName(), attval[1]);
198                     setMethod.invoke(obj, val);        //使用setter方法进行内容的赋值
199                 }
200             } catch (Exception e) { //捕获异常,否则的话一个属性不存在将会导致所有的属性都无法正常赋值
201             }
202
203         }
204     }
205
206     /**
207      * 实现属性类型转化处理
208      *
209      * @param type  属性类型,通过Field获取
210      * @param value 属性的内容,传入的都是字符串,需要将其转化为指定的类型
211      * @return 转化后的数据
212      */
213     private static Object getAttributeValue(String type, String value) {
214         if ("long".equals(type) || "java.lang.Long".equals(type)) {   //长整型
215             return Long.parseLong(value);
216         } else if ("int".equals(type) || "java.lang.Integer".equals(type)) {
217             return Integer.valueOf(value);
218         } else if ("double".equals(type) || "java.lang.Double".equals(type)) {
219             return Double.valueOf(value);
220         } else if ("java.util.Date".equals(type)) {
221             SimpleDateFormat dateFormat = null;
222             if (value.matches("\\d{4}-\\d{2}-\\d{2}")) { //日期类型
223                 dateFormat = new SimpleDateFormat("yyyy-MM-dd");
224             } else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {   //日期时间
225                 dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
226             } else {
227                 return new Date();  //当前日期
228             }
229             try {
230                 return dateFormat.parse(value);
231             } catch (ParseException e) {
232                 return new Date();
233             }
234         } else {
235             return value;
236         }
237     }
238 }
239
240 class StringUtils {
241     private StringUtils() {
242     }
243
244     public static String initcap(String str) {
245         if (str == null || str.equals("")) {
246             return str;
247         }
248         if (str.length() == 1) {
249             return str.toUpperCase();
250         } else {
251             return str.substring(0, 1).toUpperCase() + str.substring(1);
252         }
253     }
254
255 }
256
257 public class ReflectAndJavaClassDemo {
258     public static void main(String[] args) {
259         //在Emp类中,存在两个String类型的成员变量ename,job,以及其相关的getter,setter
260         String value =
261                 "ename:Mike|job:code java|empo:1258|salary:750|hireDate:1911-12-12|dept.dname:财务部" +
262                         "|dept.company.name:一个写java的公司";
263         Emp emp = ClassInstanceFactory.create(Emp.class, value);      //产生实例化对象
264         System.out.println(emp.getDept().getCompany());
265     }
266 }

--运行结果

反射.反射与java类[email protected]

Process finished with exit code 0

--这些自动的级联配置的实例化处理操作,在进行项目的编写之中将有很大的用处

六.级联属性设置
  现在已经成功实现级联对象的实例化处理,那么我们应该考虑级联的属性设置了.在之前考虑级联对象实例化处理的时候,循环进行实例化处理时数组的最后一位是没有被进行实例化的,因为数组的最后一位就是我们要操作的成员,按照之前的方式利用对象进行setter方法的调用:

  1 package 反射.反射与java类;
  2
  3 import java.lang.reflect.Field;
  4 import java.lang.reflect.Method;
  5 import java.text.ParseException;
  6 import java.text.SimpleDateFormat;
  7 import java.util.Date;
  8
  9 /**
 10  * @author : S K Y
 11  * @version :0.0.1
 12  */
 13 class Company {
 14     private String name;
 15     private Date createDate;
 16
 17     public String getName() {
 18         return name;
 19     }
 20
 21     public void setName(String name) {
 22         this.name = name;
 23     }
 24
 25     public Date getCreateDate() {
 26         return createDate;
 27     }
 28
 29     public void setCreateDate(Date createDate) {
 30         this.createDate = createDate;
 31     }
 32
 33     @Override
 34     public String toString() {
 35         return "Company{" +
 36                 "name=‘" + name + ‘\‘‘ +
 37                 ", createDate=" + createDate +
 38                 ‘}‘;
 39     }
 40 }
 41
 42 class Dept {
 43     private String dname;
 44     private String loc;
 45     private Company company;
 46
 47     public String getDname() {
 48         return dname;
 49     }
 50
 51     public void setDname(String dname) {
 52         this.dname = dname;
 53     }
 54
 55     public String getLoc() {
 56         return loc;
 57     }
 58
 59     public void setLoc(String loc) {
 60         this.loc = loc;
 61     }
 62
 63     public Company getCompany() {
 64         return company;
 65     }
 66
 67     public void setCompany(Company company) {
 68         this.company = company;
 69     }
 70
 71     @Override
 72     public String toString() {
 73         return "Dept{" +
 74                 "dname=‘" + dname + ‘\‘‘ +
 75                 ", loc=‘" + loc + ‘\‘‘ +
 76                 ", company=" + company +
 77                 ‘}‘;
 78     }
 79 }
 80
 81 class Emp {
 82     private long empo;
 83     private String ename;
 84     private String job;
 85     private double salary;
 86     private Date hireDate;
 87     private Dept dept;
 88
 89     public Dept getDept() {
 90         return dept;
 91     }
 92
 93     public void setDept(Dept dept) {
 94         this.dept = dept;
 95     }
 96
 97     public void setEname(String ename) {
 98         this.ename = ename;
 99     }
100
101     public void setJob(String job) {
102         this.job = job;
103     }
104
105     public String getEname() {
106         return ename;
107     }
108
109     public String getJob() {
110         return job;
111     }
112
113     public long getEmpo() {
114         return empo;
115     }
116
117     public void setEmpo(long empo) {
118         this.empo = empo;
119     }
120
121     public double getSalary() {
122         return salary;
123     }
124
125     public void setSalary(double salary) {
126         this.salary = salary;
127     }
128
129     public Date getHireDate() {
130         return hireDate;
131     }
132
133     public void setHireDate(Date hireDate) {
134         this.hireDate = hireDate;
135     }
136
137     @Override
138     public String toString() {
139         return "Emp{" +
140                 "empo=" + empo +
141                 ", ename=‘" + ename + ‘\‘‘ +
142                 ", job=‘" + job + ‘\‘‘ +
143                 ", salary=" + salary +
144                 ", hireDate=" + hireDate +
145                 ", dept=" + dept +
146                 ‘}‘;
147     }
148 }
149
150 class ClassInstanceFactory {
151     private ClassInstanceFactory() {
152     }        //构造方法私有化
153
154     /**
155      * 实例化对象创建的方法,该对象可以根据传入的字符串的结构"内容|属性:内容|"进行处理
156      *
157      * @param tClass 要进行反射实例化的Class类对象,有Class就可以反射实例化对象
158      * @param value  要设置给对象的属性内容
159      * @return 一个已经配置完内容的简单java类对象
160      */
161     public static <T> T create(Class<T> tClass, String value) {
162         //如果想采用反射进行简单Java类对象的属性设置的时候,类中必须要有无参构造
163         try {
164             Object o = tClass.newInstance();
165             BeanUtils.setValue(o, value);        //通过反射设置属性
166             return tClass.cast(o);    //获取对象
167         } catch (Exception e) {
168             e.printStackTrace();        //此时如果出现异常,将异常抛出也没有多大作用
169             return null;
170         }
171
172
173     }
174
175 }
176
177 class BeanUtils {    //进行Bean处理的工具类
178     private BeanUtils() {
179     }
180
181     /**
182      * 实现指定对象的属性设置
183      *
184      * @param obj   要进行反射操作的实例化对象
185      * @param value 包含有指定内容的字符串
186      */
187     public static void setValue(Object obj, String value) {
188         String results[] = value.split("\\|");//按照竖线进行每一组属性的拆分
189         for (int i = 0; i < results.length; i++) {  //循环设置属性内容
190             String attval[] = results[i].split(":");   //获取属性名称及内容
191             try {
192                 Object currentObject = obj;
193                 if (attval[0].contains(".")) {        //这是多级配置
194                     String temp[] = attval[0].split("\\.");
195                     //最后一位肯定是指定类中的属性名称,因此不在实例化处理的范畴之内
196                     for (int j = 0; j < temp.length - 1; j++) {  //实例化
197                         //调用相应的getter方法,如果getter方法返回了空表示该对象为实例化
198                         Method getMethod = currentObject.getClass().getDeclaredMethod(
199                                 "get" + StringUtils.initcap(temp[j]));
200                         if (getMethod.invoke(currentObject) == null) {  //该对象现在并没有被实例化
201                             Field field = currentObject.getClass().getDeclaredField(temp[j]);
202                             Method method = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[j]), field.getType());
203                             Object newObject = field.getType().getDeclaredConstructor().newInstance();
204                             method.invoke(currentObject, newObject);
205                             currentObject = newObject;
206                         } else {
207                             currentObject = getMethod.invoke(currentObject);
208                         }
209                     }
210                     //进行属性内容的 设置
211                     Field field = currentObject.getClass().getDeclaredField(temp[temp.length - 1]);
212                     Method setMethod = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[temp.length - 1]), field.getType());
213                     Object val = BeanUtils.getAttributeValue(field.getType().getName(), attval[1]);
214                     setMethod.invoke(currentObject, val);        //使用setter方法进行内容的赋值
215                 } else {
216                     Field field = obj.getClass().getDeclaredField(attval[0]);
217                     Method setMethod = obj.getClass()
218                             .getDeclaredMethod("set" + StringUtils.initcap(attval[0]), field.getType());
219                     Object val = BeanUtils.getAttributeValue(field.getType().getName(), attval[1]);
220                     setMethod.invoke(obj, val);        //使用setter方法进行内容的赋值
221                 }
222             } catch (Exception e) { //捕获异常,否则的话一个属性不存在将会导致所有的属性都无法正常赋值
223             }
224
225         }
226     }
227
228     /**
229      * 实现属性类型转化处理
230      *
231      * @param type  属性类型,通过Field获取
232      * @param value 属性的内容,传入的都是字符串,需要将其转化为指定的类型
233      * @return 转化后的数据
234      */
235     private static Object getAttributeValue(String type, String value) {
236         if ("long".equals(type) || "java.lang.Long".equals(type)) {   //长整型
237             return Long.parseLong(value);
238         } else if ("int".equals(type) || "java.lang.Integer".equals(type)) {
239             return Integer.valueOf(value);
240         } else if ("double".equals(type) || "java.lang.Double".equals(type)) {
241             return Double.valueOf(value);
242         } else if ("java.util.Date".equals(type)) {
243             SimpleDateFormat dateFormat = null;
244             if (value.matches("\\d{4}-\\d{2}-\\d{2}")) { //日期类型
245                 dateFormat = new SimpleDateFormat("yyyy-MM-dd");
246             } else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {   //日期时间
247                 dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
248             } else {
249                 return new Date();  //当前日期
250             }
251             try {
252                 return dateFormat.parse(value);
253             } catch (ParseException e) {
254                 return new Date();
255             }
256         } else {
257             return value;
258         }
259     }
260 }
261
262 class StringUtils {
263     private StringUtils() {
264     }
265
266     public static String initcap(String str) {
267         if (str == null || str.equals("")) {
268             return str;
269         }
270         if (str.length() == 1) {
271             return str.toUpperCase();
272         } else {
273             return str.substring(0, 1).toUpperCase() + str.substring(1);
274         }
275     }
276
277 }
278
279 public class ReflectAndJavaClassDemo {
280     public static void main(String[] args) {
281         //在Emp类中,存在两个String类型的成员变量ename,job,以及其相关的getter,setter
282         String value =
283                 "ename:Mike|job:code java|empo:1258|salary:750|hireDate:1911-12-12|dept.dname:财务部" +
284                         "|dept.company.name:一个写java的公司";
285         Emp emp = ClassInstanceFactory.create(Emp.class, value);      //产生实例化对象
286         System.out.println(emp);
287     }
288 }

--运行结果

Emp{empo=1258, ename=‘Mike‘, job=‘code java‘, salary=750.0, hireDate=Tue Dec 12 00:00:00 CST 1911, dept=Dept{dname=‘财务部‘, loc=‘null‘, company=Company{name=‘一个写java的公司‘, createDate=null}}}

Process finished with exit code 0

--这样在以后的简单java类的赋值处理将不再重复调用setter操作来完成,而这种形式,是在正规开发之中普遍采用的方式

原文地址:https://www.cnblogs.com/skykuqi/p/11432490.html

时间: 2024-11-05 12:20:47

java反射(四)--反射与简单java类的相关文章

JAVA基础学习之路(四)定义简单java类

简单java类开发一般原则: 类名称必须有意义,再怎么说,要让人家看的明白吧 类之中所有属性必须使用private封装,并提供setter,getter方法 类之中可以有多个构造方法,但是必须保留有一个无参数构造方法 类之中不允许出现任何输出语句,所有输出必须交给被调用处 类之中需要有一个可以取得对象完整信息的方法,一般叫做getInfo(),返回String型数据 class Book { private String name; private int price; private int

Java基础_3.5:简单Java类

简单Java类 简单Java类是一种在实际开发之中使用最多的类的定义形式,在简单Java类中包含有类.对象.构造方法.private封装等核心概念的使用,而对于简单Java类首先给出如下的基本开发要求: 类名称必须存在有意义,例如:Book.Emp: 类之中所有的属性必须private封装,封装后的属性必须提供有setter.getter: 类之中可以提供有任意多个构造方法,但是必须保留有一个无参构造方法: 类之中不允许出现任何的输出语句,所有信息输出必须交给被调用处输出: 类之中需要提供有一个

Java的int数组的简单工具类IntArrayUtil1.0

数组越界异常真是令人感觉闹心,又不是很烦.集合是很好的工具,每次用集合处理小数据显得有点小题大做. 如下是一个简单IntArrayUtil工具类(简陋程度,自己都想捂脸,不知道拿这东西水自己的博客,会不会被人打,/手动滑稽). package cn.util; /** * 整数数组工具类: 一维数组的创建和设置值,二维数组的创建和设置值. * * @author JXLYS * @version 1.0 */ public class IntArrayUtil { /** * 获得一维数组指定位

java 反射机制:运行时的类信息(为框架服务的Bug存在)

反射机制:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 换一种引出反射的说法是:当通过反射与一个未知的类型的对象打交道是,JVM只是简单地检查这个类,看它是属于哪个特定的类(就想RTTI那样).在用它做其他事情之前必须先加载那个类的Class对象.因此,那个类的.class文件对于JVM来说必须是可获取的:那么在本地机器上,要么通过网络获得

java反射机制剖析(三)—类类型Class

为了区别于我们常用的Class,因此给了个中文名类类型.目的就是为了知道此Class非彼Class.上一篇博客已经介绍了Class Loader,它的作用是根据提供的信息来加载类到内存中.我之前有提过这个类信息的提供者就是本篇博客要介绍的Class.提醒:一个类的Class对象和它的Instance是不一样的,切记,不然你会混乱的.开始了! 概念 Class类是所有类(注意是对象)的共有信息的抽象,比如该类实现的接口.对应的加载器.类名等等.一句话,类类型保存了每个类所对应的类型信息.每一个类都

跟王老师学反射(二):Java类的加载、连接和初始化

跟王老师学反射(二):Java类的加载.连接和初始化 主讲教师:王少华   QQ群号:483773664 学习内容: 了解类的加载.连接和初始化 一.类的生命周期 当我们编写一个java的源文件后,经过编译会生成一个后缀名为class的文件,这种文件叫做字节码文件,只有这种字节码文件才能够在java虚拟机中运行,java类的生命周期就是指一个class文件从加载到卸载的全过程.一个java类的完整的生命周期会经历加载.连接.初始化.使用.和卸载五个阶段,当然也有在加载或者连接之后没有被初始化就直

java进阶之反射:反射基础之如何获取一个类以及如何获取这个类的所有属性和方法(1)

java学习一段时间之后,大家可能经常会听到反射这个词,那么说明java已经学习到一个高一点的层次了.接下来我会一步步和大家一起揭开java高级特性反射的神秘面纱. 首先介绍下类对象这个概念,可能会经常用到这个概念: 类对象:java中有句很经典的话"万事万物皆对象",相信大家都不陌生,这句话告诉了我们java的特征之一,那就是面向对象.java中类的概念我们都很熟悉,既然万事万物皆是对象,那么类是谁的对象呢?<对象的概念:一个类的实例>换句话说,类是谁的实例.如此就有了类

java 27 - 1 反射之 类的加载器

说到反射,首先说类的加载器. 类的加载: 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. 加载: 就是指将class文件读入内存,并为之创建一个Class对象. 任何类被使用时系统都会建立一个Class对象. 连接: 验证 是否有正确的内部结构,并和其他类协调一致 准备 负责为类的静态成员分配内存,并设置默认初始化值 解析 将类的二进制数据中的符号引用替换为直接引用 初始化: 就是我们以前讲过的初始化步骤 类初始化时机: 创建类的实

从零开始学java (四)反射

反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. Class 类 ,一个Class对象将表示一个类的属性:获取Class类一共有三种方式如下 package javase.first; /** * @author fqh * @Date 2017年4月12日:上午8:15:01 */ public class Employee { //属性,私有