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类.Company@610455d6

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操作来完成,而这种形式,是在正规开发之中普遍采用的方式

posted @ 2019-08-29 22:45  灰色天空_graySky  阅读(314)  评论(0编辑  收藏  举报