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