java反射(四)--反射与简单java类
一.传统简单java类
简单的java类主要是由属性所组成,并且提供有相应的setter以及getter的处理方法,同时简单java类最大的特征就是通过对象保存相应的类的属性内容,但是如果使用传统的简单java类的开发,那么也会面临非常麻烦的困难:
class Emp{
private String ename;
private String job; public void setEname(String ename) {
this.ename = ename;
} public void setJob(String job) {
this.job = job;
} public String getEname() {
return ename;
} public String getJob() {
return job;
}
}
--按照传统的做法,首先应该实例化Emp对象,而后通过实例化对象进行setter方法的调用来设置属性的内容:
class Emp{
private String ename;
private String job; public void setEname(String ename) {
this.ename = ename;
} public void setJob(String job) {
this.job = job;
} public String getEname() {
return ename;
} public String getJob() {
return job;
}
}
public class ReflectAndJavaClassDemo {
public static void main(String[] args) {
Emp emp = new Emp();
emp.setEname("Mike");
emp.setJob("code java");
System.out.println("姓名: " + emp.getEname() + " 职位: " + emp.getJob());
}
}
--在整个进行Emp对象实例化并设置数据的操作过程之中,设置数据的部分是为麻烦的,可以想象如果现在Emp类中提供有50个属性,那么对于整个程序而言,将成为一大堆的setter方法的调用,即使使用构造方法赋值,也会造成很多的麻烦.或者咱们再进一步说明,在一个开发之中,简单java类的个数是非常多的,那么如果所有的简单java类都牵扯到属性赋值的问题时,我们代码的重复率会非常的高.按照传统直观的编程方式所带来的问题就是代码会存在大量的重复操作,如果要想解决对象的重复处理操作,那么唯一的解决方案就是反射机制,反射机制最大的特征就是可以根据其自身的特点(Object类直接操作属性和方法,实现相同功能类的重复操作的抽象处理).
二.属性自动设置解决方案:
经过了分析之后已经确认了当前简单java类操作的问题所在,而对于开发者而言就需要想办法通过一种解决方案来实现属性内容的自动设置,那么这个时候的设置强烈建议采用字符串的形式来描述对应的类型:
--1.在进行程序开发的时候我们可以知道String字符串可以描述的类型由很多,并且也可以由开发者自行定义String字符串的结构,我们采用"内容|属性:内容|"的形式来为简单java类中的属性进行初始化;
--2.类设计的基本结构,应该由一个专门的工具类(ClassInstanceFactory类)负责所有的反射处理,即接收反射对象,同时可以获取指定类的实例化对象;
--3.设计的基本结构
package 反射.反射与java类; /**
* @author : S K Y
* @version :0.0.1
*/
class Emp {
private String ename;
private String job; public void setEname(String ename) {
this.ename = ename;
} public void setJob(String job) {
this.job = job;
} public String getEname() {
return ename;
} public String getJob() {
return job;
}
} class ClassInstanceFactory {
private ClassInstanceFactory() {
} //构造方法私有化 /**
* 实例化对象创建的方法,该对象可以根据传入的字符串的结构"内容|属性:内容|"进行处理
*
* @param tClass 要进行反射实例化的Class类对象,有Class就可以反射实例化对象
* @param value 要设置给对象的属性内容
* @return 一个已经配置完内容的简单java类对象
*/
public static <T> T create(Class<T> tClass, String value) {
return null;
} } public class ReflectAndJavaClassDemo {
public static void main(String[] args) {
//在Emp类中,存在两个String类型的成员变量ename,job,以及其相关的getter,setter
String value = "ename:Mike|job:code java";
Emp emp = ClassInstanceFactory.create(Emp.class, value); //产生实例化对象
}
}
--这样在当前的开发之中,所需要留给用户完善的就是ClassInstanceFactory.create()方法的具体实现
三.单级属性配置
对于此时的Emp类型里面会发现所给出的数据类型都没有其他的引用关联了,只是描述了Emp本类的对象,这样的设置我们称他为单级属性配置,所以此时应该需要处理两件事情:
--1.需要通过反射进行指定类对象的实例化处理;
--2.进行内容的设置(Field属性类型,方法名称,要设置的内容)
package 反射.反射与java类; import java.lang.reflect.Field;
import java.lang.reflect.Method; /**
* @author : S K Y
* @version :0.0.1
*/
class Emp {
private String ename;
private String job; public void setEname(String ename) {
this.ename = ename;
} public void setJob(String job) {
this.job = job;
} public String getEname() {
return ename;
} public String getJob() {
return job;
}
} class ClassInstanceFactory {
private ClassInstanceFactory() {
} //构造方法私有化 /**
* 实例化对象创建的方法,该对象可以根据传入的字符串的结构"内容|属性:内容|"进行处理
*
* @param tClass 要进行反射实例化的Class类对象,有Class就可以反射实例化对象
* @param value 要设置给对象的属性内容
* @return 一个已经配置完内容的简单java类对象
*/
public static <T> T create(Class<T> tClass, String value) {
//如果想采用反射进行简单Java类对象的属性设置的时候,类中必须要有无参构造
try {
Object o = tClass.newInstance();
BeanUtils.setValue(o, value); //通过反射设置属性
return tClass.cast(o); //获取对象
} catch (Exception e) {
e.printStackTrace(); //此时如果出现异常,将异常抛出也没有多大作用
return null;
} } } class BeanUtils { //进行Bean处理的工具类
private BeanUtils() {
} /**
* 实现指定对象的属性设置
*
* @param obj 要进行反射操作的实例化对象
* @param value 包含有指定内容的字符串
*/
public static void setValue(Object obj, String value) {
String results[] = value.split("\\|");//按照竖线进行每一组属性的拆分
for (int i = 0; i < results.length; i++) { //循环设置属性内容
String attval[] = results[i].split(":"); //获取属性名称及内容
try {
Field field = obj.getClass().getDeclaredField(attval[0]);
Method setMethod = obj.getClass()
.getDeclaredMethod("set" + StringUtils.initcap(attval[0]), field.getType());
setMethod.invoke(obj,attval[1]); //使用setter方法进行内容的赋值
} catch (Exception e) { //捕获异常,否则的话一个属性不存在将会导致所有的属性都无法正常赋值
} }
}
} class StringUtils {
private StringUtils() {
} public static String initcap(String str) {
if (str == null || str.equals("")) {
return str;
}
if (str.length() == 1) {
return str.toUpperCase();
} else {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
} } public class ReflectAndJavaClassDemo {
public static void main(String[] args) {
//在Emp类中,存在两个String类型的成员变量ename,job,以及其相关的getter,setter
String value = "ename:Mike|job:code java";
Emp emp = ClassInstanceFactory.create(Emp.class, value); //产生实例化对象
System.out.println("姓名: " + emp.getEname() + " 职位: " + emp.getJob());
}
}
--运行结果
姓名: Mike 职位: code java Process finished with exit code 0
--ClassInstanceFactory负责实例化对象并且调用BeanUtils类实现属性代码的设置,此时即便类中的属性再多,那么也可以轻松的实现setter的调用,轻松实现类对象实例化处理
四.设置多种数据类型
虽然上述代码可以实现对于属性的配置,但是我们仍然需要考虑一个实际的情况,当前所给定的数据类型只能是String,但是在实际的开发之中,面对简单java类中的属性类型一般的可选为:Long(long),Integer(int),Double(double),String,Date(日期,日期时间),所以这个时候对于当前的程序代码就必须做出修改,要求可以实现各种数据类型的配置.
--既然要求可以实现不同类型的内容设置,并且BeanUtils类主要是完成属性赋值处理的,那么就可以在这个类之中追加有一些列的处理方法:
package 反射.反射与java类; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; /**
* @author : S K Y
* @version :0.0.1
*/
class Emp {
private long empo;
private String ename;
private String job;
private double salary;
private Date hireDate; public void setEname(String ename) {
this.ename = ename;
} public void setJob(String job) {
this.job = job;
} public String getEname() {
return ename;
} public String getJob() {
return job;
} public long getEmpo() {
return empo;
} public void setEmpo(long empo) {
this.empo = empo;
} public double getSalary() {
return salary;
} public void setSalary(double salary) {
this.salary = salary;
} public Date getHireDate() {
return hireDate;
} public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
} @Override
public String toString() {
return "Emp{" +
"empo=" + empo +
", ename='" + ename + '\'' +
", job='" + job + '\'' +
", salary=" + salary +
", hireDate=" + hireDate +
'}';
}
} class ClassInstanceFactory {
private ClassInstanceFactory() {
} //构造方法私有化 /**
* 实例化对象创建的方法,该对象可以根据传入的字符串的结构"内容|属性:内容|"进行处理
*
* @param tClass 要进行反射实例化的Class类对象,有Class就可以反射实例化对象
* @param value 要设置给对象的属性内容
* @return 一个已经配置完内容的简单java类对象
*/
public static <T> T create(Class<T> tClass, String value) {
//如果想采用反射进行简单Java类对象的属性设置的时候,类中必须要有无参构造
try {
Object o = tClass.newInstance();
BeanUtils.setValue(o, value); //通过反射设置属性
return tClass.cast(o); //获取对象
} catch (Exception e) {
e.printStackTrace(); //此时如果出现异常,将异常抛出也没有多大作用
return null;
} } } class BeanUtils { //进行Bean处理的工具类
private BeanUtils() {
} /**
* 实现指定对象的属性设置
*
* @param obj 要进行反射操作的实例化对象
* @param value 包含有指定内容的字符串
*/
public static void setValue(Object obj, String value) {
String results[] = value.split("\\|");//按照竖线进行每一组属性的拆分
for (int i = 0; i < results.length; i++) { //循环设置属性内容
String attval[] = results[i].split(":"); //获取属性名称及内容
try {
Field field = obj.getClass().getDeclaredField(attval[0]);
Method setMethod = obj.getClass()
.getDeclaredMethod("set" + StringUtils.initcap(attval[0]), field.getType());
Object val = BeanUtils.getAttributeValue(field.getType().getName(), attval[1]);
setMethod.invoke(obj, val); //使用setter方法进行内容的赋值
} catch (Exception e) { //捕获异常,否则的话一个属性不存在将会导致所有的属性都无法正常赋值
} }
} /**
* 实现属性类型转化处理
*
* @param type 属性类型,通过Field获取
* @param value 属性的内容,传入的都是字符串,需要将其转化为指定的类型
* @return 转化后的数据
*/
private static Object getAttributeValue(String type, String value) {
if ("long".equals(type) || "java.lang.Long".equals(type)) { //长整型
return Long.parseLong(value);
} else if ("int".equals(type) || "java.lang.Integer".equals(type)) {
return Integer.valueOf(value);
} else if ("double".equals(type) || "java.lang.Double".equals(type)) {
return Double.valueOf(value);
} else if ("java.util.Date".equals(type)) {
SimpleDateFormat dateFormat = null;
if (value.matches("\\d{4}-\\d{2}-\\d{2}")) { //日期类型
dateFormat = new SimpleDateFormat("yyyy-MM-dd");
} else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) { //日期时间
dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
} else {
return new Date(); //当前日期
}
try {
return dateFormat.parse(value);
} catch (ParseException e) {
return new Date();
}
} else {
return value;
}
}
} class StringUtils {
private StringUtils() {
} public static String initcap(String str) {
if (str == null || str.equals("")) {
return str;
}
if (str.length() == 1) {
return str.toUpperCase();
} else {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
} } public class ReflectAndJavaClassDemo {
public static void main(String[] args) {
//在Emp类中,存在两个String类型的成员变量ename,job,以及其相关的getter,setter
String value = "ename:Mike|job:code java|empo:1258|salary:750|hireDate:1911-12-12";
Emp emp = ClassInstanceFactory.create(Emp.class, value); //产生实例化对象
System.out.println(emp);
}
}
--运行结果
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类的定义如下:
class Company {
private String name;
private Date createDate; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Date getCreateDate() {
return createDate;
} public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
} class Dept {
private String dname;
private String loc;
private Company company; public String getDname() {
return dname;
} public void setDname(String dname) {
this.dname = dname;
} public String getLoc() {
return loc;
} public void setLoc(String loc) {
this.loc = loc;
} public Company getCompany() {
return company;
} public void setCompany(Company company) {
this.company = company;
}
} class Emp {
private long empo;
private String ename;
private String job;
private double salary;
private Date hireDate;
private Dept dept; public Dept getDept() {
return dept;
} public void setDept(Dept dept) {
this.dept = dept;
} public void setEname(String ename) {
this.ename = ename;
} public void setJob(String job) {
this.job = job;
} public String getEname() {
return ename;
} public String getJob() {
return job;
} public long getEmpo() {
return empo;
} public void setEmpo(long empo) {
this.empo = empo;
} public double getSalary() {
return salary;
} public void setSalary(double salary) {
this.salary = salary;
} public Date getHireDate() {
return hireDate;
} public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
} @Override
public String toString() {
return "Emp{" +
"empo=" + empo +
", ename='" + ename + '\'' +
", job='" + job + '\'' +
", salary=" + salary +
", hireDate=" + hireDate +
'}';
}
}
--如果要通过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的公司";现在的属性存在多级关系,那么对于多级的关系就必须与单级的配置区分开
package 反射.反射与java类; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date; /**
* @author : S K Y
* @version :0.0.1
*/
class Company {
private String name;
private Date createDate; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Date getCreateDate() {
return createDate;
} public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
} class Dept {
private String dname;
private String loc;
private Company company; public String getDname() {
return dname;
} public void setDname(String dname) {
this.dname = dname;
} public String getLoc() {
return loc;
} public void setLoc(String loc) {
this.loc = loc;
} public Company getCompany() {
return company;
} public void setCompany(Company company) {
this.company = company;
}
} class Emp {
private long empo;
private String ename;
private String job;
private double salary;
private Date hireDate;
private Dept dept; public Dept getDept() {
return dept;
} public void setDept(Dept dept) {
this.dept = dept;
} public void setEname(String ename) {
this.ename = ename;
} public void setJob(String job) {
this.job = job;
} public String getEname() {
return ename;
} public String getJob() {
return job;
} public long getEmpo() {
return empo;
} public void setEmpo(long empo) {
this.empo = empo;
} public double getSalary() {
return salary;
} public void setSalary(double salary) {
this.salary = salary;
} public Date getHireDate() {
return hireDate;
} public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
} @Override
public String toString() {
return "Emp{" +
"empo=" + empo +
", ename='" + ename + '\'' +
", job='" + job + '\'' +
", salary=" + salary +
", hireDate=" + hireDate +
'}';
}
} class ClassInstanceFactory {
private ClassInstanceFactory() {
} //构造方法私有化 /**
* 实例化对象创建的方法,该对象可以根据传入的字符串的结构"内容|属性:内容|"进行处理
*
* @param tClass 要进行反射实例化的Class类对象,有Class就可以反射实例化对象
* @param value 要设置给对象的属性内容
* @return 一个已经配置完内容的简单java类对象
*/
public static <T> T create(Class<T> tClass, String value) {
//如果想采用反射进行简单Java类对象的属性设置的时候,类中必须要有无参构造
try {
Object o = tClass.newInstance();
BeanUtils.setValue(o, value); //通过反射设置属性
return tClass.cast(o); //获取对象
} catch (Exception e) {
e.printStackTrace(); //此时如果出现异常,将异常抛出也没有多大作用
return null;
} } } class BeanUtils { //进行Bean处理的工具类
private BeanUtils() {
} /**
* 实现指定对象的属性设置
*
* @param obj 要进行反射操作的实例化对象
* @param value 包含有指定内容的字符串
*/
public static void setValue(Object obj, String value) {
String results[] = value.split("\\|");//按照竖线进行每一组属性的拆分
for (int i = 0; i < results.length; i++) { //循环设置属性内容
String attval[] = results[i].split(":"); //获取属性名称及内容
try {
Object currentObject = obj;
if (attval[0].contains(".")) { //这是多级配置
String temp[] = attval[0].split("\\.");
//最后一位肯定是指定类中的属性名称,因此不在实例化处理的范畴之内
for (int j = 0; j < temp.length - 1; j++) { //实例化
//调用相应的getter方法,如果getter方法返回了空表示该对象为实例化
Method getMethod = currentObject.getClass().getDeclaredMethod(
"get" + StringUtils.initcap(temp[j]));
if (getMethod.invoke(currentObject) == null) { //该对象现在并没有被实例化
Field field = currentObject.getClass().getDeclaredField(temp[j]);
Method method = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[j]), field.getType());
Object newObject = field.getType().getDeclaredConstructor().newInstance();
method.invoke(currentObject, newObject);
currentObject = newObject;
} else {
currentObject = getMethod.invoke(currentObject);
}
}
} else {
Field field = obj.getClass().getDeclaredField(attval[0]);
Method setMethod = obj.getClass()
.getDeclaredMethod("set" + StringUtils.initcap(attval[0]), field.getType());
Object val = BeanUtils.getAttributeValue(field.getType().getName(), attval[1]);
setMethod.invoke(obj, val); //使用setter方法进行内容的赋值
}
} catch (Exception e) { //捕获异常,否则的话一个属性不存在将会导致所有的属性都无法正常赋值
} }
} /**
* 实现属性类型转化处理
*
* @param type 属性类型,通过Field获取
* @param value 属性的内容,传入的都是字符串,需要将其转化为指定的类型
* @return 转化后的数据
*/
private static Object getAttributeValue(String type, String value) {
if ("long".equals(type) || "java.lang.Long".equals(type)) { //长整型
return Long.parseLong(value);
} else if ("int".equals(type) || "java.lang.Integer".equals(type)) {
return Integer.valueOf(value);
} else if ("double".equals(type) || "java.lang.Double".equals(type)) {
return Double.valueOf(value);
} else if ("java.util.Date".equals(type)) {
SimpleDateFormat dateFormat = null;
if (value.matches("\\d{4}-\\d{2}-\\d{2}")) { //日期类型
dateFormat = new SimpleDateFormat("yyyy-MM-dd");
} else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) { //日期时间
dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
} else {
return new Date(); //当前日期
}
try {
return dateFormat.parse(value);
} catch (ParseException e) {
return new Date();
}
} else {
return value;
}
}
} class StringUtils {
private StringUtils() {
} public static String initcap(String str) {
if (str == null || str.equals("")) {
return str;
}
if (str.length() == 1) {
return str.toUpperCase();
} else {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
} } public class ReflectAndJavaClassDemo {
public static void main(String[] args) {
//在Emp类中,存在两个String类型的成员变量ename,job,以及其相关的getter,setter
String value =
"ename:Mike|job:code java|empo:1258|salary:750|hireDate:1911-12-12|dept.dname:财务部" +
"|dept.company.name:一个写java的公司";
Emp emp = ClassInstanceFactory.create(Emp.class, value); //产生实例化对象
System.out.println(emp.getDept().getCompany());
}
}
--运行结果
反射.反射与java类.Company@610455d6 Process finished with exit code 0
--这些自动的级联配置的实例化处理操作,在进行项目的编写之中将有很大的用处
六.级联属性设置
现在已经成功实现级联对象的实例化处理,那么我们应该考虑级联的属性设置了.在之前考虑级联对象实例化处理的时候,循环进行实例化处理时数组的最后一位是没有被进行实例化的,因为数组的最后一位就是我们要操作的成员,按照之前的方式利用对象进行setter方法的调用:
package 反射.反射与java类; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; /**
* @author : S K Y
* @version :0.0.1
*/
class Company {
private String name;
private Date createDate; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Date getCreateDate() {
return createDate;
} public void setCreateDate(Date createDate) {
this.createDate = createDate;
} @Override
public String toString() {
return "Company{" +
"name='" + name + '\'' +
", createDate=" + createDate +
'}';
}
} class Dept {
private String dname;
private String loc;
private Company company; public String getDname() {
return dname;
} public void setDname(String dname) {
this.dname = dname;
} public String getLoc() {
return loc;
} public void setLoc(String loc) {
this.loc = loc;
} public Company getCompany() {
return company;
} public void setCompany(Company company) {
this.company = company;
} @Override
public String toString() {
return "Dept{" +
"dname='" + dname + '\'' +
", loc='" + loc + '\'' +
", company=" + company +
'}';
}
} class Emp {
private long empo;
private String ename;
private String job;
private double salary;
private Date hireDate;
private Dept dept; public Dept getDept() {
return dept;
} public void setDept(Dept dept) {
this.dept = dept;
} public void setEname(String ename) {
this.ename = ename;
} public void setJob(String job) {
this.job = job;
} public String getEname() {
return ename;
} public String getJob() {
return job;
} public long getEmpo() {
return empo;
} public void setEmpo(long empo) {
this.empo = empo;
} public double getSalary() {
return salary;
} public void setSalary(double salary) {
this.salary = salary;
} public Date getHireDate() {
return hireDate;
} public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
} @Override
public String toString() {
return "Emp{" +
"empo=" + empo +
", ename='" + ename + '\'' +
", job='" + job + '\'' +
", salary=" + salary +
", hireDate=" + hireDate +
", dept=" + dept +
'}';
}
} class ClassInstanceFactory {
private ClassInstanceFactory() {
} //构造方法私有化 /**
* 实例化对象创建的方法,该对象可以根据传入的字符串的结构"内容|属性:内容|"进行处理
*
* @param tClass 要进行反射实例化的Class类对象,有Class就可以反射实例化对象
* @param value 要设置给对象的属性内容
* @return 一个已经配置完内容的简单java类对象
*/
public static <T> T create(Class<T> tClass, String value) {
//如果想采用反射进行简单Java类对象的属性设置的时候,类中必须要有无参构造
try {
Object o = tClass.newInstance();
BeanUtils.setValue(o, value); //通过反射设置属性
return tClass.cast(o); //获取对象
} catch (Exception e) {
e.printStackTrace(); //此时如果出现异常,将异常抛出也没有多大作用
return null;
} } } class BeanUtils { //进行Bean处理的工具类
private BeanUtils() {
} /**
* 实现指定对象的属性设置
*
* @param obj 要进行反射操作的实例化对象
* @param value 包含有指定内容的字符串
*/
public static void setValue(Object obj, String value) {
String results[] = value.split("\\|");//按照竖线进行每一组属性的拆分
for (int i = 0; i < results.length; i++) { //循环设置属性内容
String attval[] = results[i].split(":"); //获取属性名称及内容
try {
Object currentObject = obj;
if (attval[0].contains(".")) { //这是多级配置
String temp[] = attval[0].split("\\.");
//最后一位肯定是指定类中的属性名称,因此不在实例化处理的范畴之内
for (int j = 0; j < temp.length - 1; j++) { //实例化
//调用相应的getter方法,如果getter方法返回了空表示该对象为实例化
Method getMethod = currentObject.getClass().getDeclaredMethod(
"get" + StringUtils.initcap(temp[j]));
if (getMethod.invoke(currentObject) == null) { //该对象现在并没有被实例化
Field field = currentObject.getClass().getDeclaredField(temp[j]);
Method method = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[j]), field.getType());
Object newObject = field.getType().getDeclaredConstructor().newInstance();
method.invoke(currentObject, newObject);
currentObject = newObject;
} else {
currentObject = getMethod.invoke(currentObject);
}
}
//进行属性内容的 设置
Field field = currentObject.getClass().getDeclaredField(temp[temp.length - 1]);
Method setMethod = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[temp.length - 1]), field.getType());
Object val = BeanUtils.getAttributeValue(field.getType().getName(), attval[1]);
setMethod.invoke(currentObject, val); //使用setter方法进行内容的赋值
} else {
Field field = obj.getClass().getDeclaredField(attval[0]);
Method setMethod = obj.getClass()
.getDeclaredMethod("set" + StringUtils.initcap(attval[0]), field.getType());
Object val = BeanUtils.getAttributeValue(field.getType().getName(), attval[1]);
setMethod.invoke(obj, val); //使用setter方法进行内容的赋值
}
} catch (Exception e) { //捕获异常,否则的话一个属性不存在将会导致所有的属性都无法正常赋值
} }
} /**
* 实现属性类型转化处理
*
* @param type 属性类型,通过Field获取
* @param value 属性的内容,传入的都是字符串,需要将其转化为指定的类型
* @return 转化后的数据
*/
private static Object getAttributeValue(String type, String value) {
if ("long".equals(type) || "java.lang.Long".equals(type)) { //长整型
return Long.parseLong(value);
} else if ("int".equals(type) || "java.lang.Integer".equals(type)) {
return Integer.valueOf(value);
} else if ("double".equals(type) || "java.lang.Double".equals(type)) {
return Double.valueOf(value);
} else if ("java.util.Date".equals(type)) {
SimpleDateFormat dateFormat = null;
if (value.matches("\\d{4}-\\d{2}-\\d{2}")) { //日期类型
dateFormat = new SimpleDateFormat("yyyy-MM-dd");
} else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) { //日期时间
dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
} else {
return new Date(); //当前日期
}
try {
return dateFormat.parse(value);
} catch (ParseException e) {
return new Date();
}
} else {
return value;
}
}
} class StringUtils {
private StringUtils() {
} public static String initcap(String str) {
if (str == null || str.equals("")) {
return str;
}
if (str.length() == 1) {
return str.toUpperCase();
} else {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
} } public class ReflectAndJavaClassDemo {
public static void main(String[] args) {
//在Emp类中,存在两个String类型的成员变量ename,job,以及其相关的getter,setter
String value =
"ename:Mike|job:code java|empo:1258|salary:750|hireDate:1911-12-12|dept.dname:财务部" +
"|dept.company.name:一个写java的公司";
Emp emp = ClassInstanceFactory.create(Emp.class, value); //产生实例化对象
System.out.println(emp);
}
}
--运行结果
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操作来完成,而这种形式,是在正规开发之中普遍采用的方式
java反射(四)--反射与简单java类的更多相关文章
- JAVA基础学习之路(四)定义简单java类
简单java类开发一般原则: 类名称必须有意义,再怎么说,要让人家看的明白吧 类之中所有属性必须使用private封装,并提供setter,getter方法 类之中可以有多个构造方法,但是必须保留有一 ...
- 菜鸡的Java笔记 数据表与简单java类映射
利用实际的数据表实现表与类的操作转换 简单java类是整个项目开发中的灵魂所在,它有自己严格的开发标准,而最为重要的是它需要于数据表是完全对应的 不过考虑到现在没有接触到过 ...
- java构造方法的作用以及简单java类
public class TestDemo{ public static void main(String args[]){ Emp emp1 =new Emp(001,"tom" ...
- java--分析简单java类与反射的联系
分析简单java类与反射的联系 web对反射的操作支持 在JSP之中有一种技术--javaBean.而且在jsp里面也配套有相应的操作方式,javaBean的核心在于简单java类,于是下面演示此操作 ...
- 进阶Java编程(10)反射与简单Java类
1,传统属性自动赋值弊端 简单Java类主要由属性构成,并且提供有setter与getter类,同时简单Java类最大的特征就是通过对象保存相应的类属性的内容.但是如果使用传统的简单Java类开发,那 ...
- java中的反射机制,以及如何通过反射获取一个类的构造方法 ,成员变量,方法,详细。。
首先先说一下类的加载,流程.只有明确了类这个对象的存在才可以更好的理解反射的原因,以及反射的机制. 一. 类的加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三 ...
- 深入分析Java反射(四)-动态代理
动态代理的简介 Java动态代理机制的出现,使得Java开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分 ...
- Java 反射理解(一)-- Class 类的使用
Java 反射理解(一)-- Class 类的使用 概念 这里阐述几个基本概念: 在面向对象的世界里,万事万物皆对象.(在 Java 语言中,静态的成员.普通数据类型除外) 类也是对象,类是 java ...
- java反射(三)--反射与操作类
一.反射与操作类 在反射机制的处理过程之中不仅仅只是一个实例化对象的处理操作,更多的情况下还有类的组成的操作,任何一个类的基本组成结构:父类(父接口),包,属性,方法(构造方法,普通方法)--获取类的 ...
随机推荐
- HDU 1255 覆盖的面积 ( 扫描线 + 离散 求矩阵大于k次面积并 )
覆盖的面积 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Subm ...
- 2019 Multi-University Training Contest 1 - 1012 - NTT
题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=6589 题解连接: https://www.cnblogs.com/xusirui/p/1122945 ...
- hdu6341 Problem J. Let Sudoku Rotate (dfs)
题目传送门 题意: 给你16个16宫格的数独,里面是0~F,你可以逆时针旋转里面的每个16宫格 问你它是从标准数独逆时针旋转多少次得到? 思路: 可以知道每个16宫已经是标准的了,接下来只要考虑每行. ...
- 72.Minimum Window Substring(最小子串窗口)
Level: Hard 题目描述: Given a string S and a string T, find the minimum window in S which will contain ...
- idea 2019.1.3最新注册码
CATF44LT7C-eyJsaWNlbnNlSWQiOiJDQVRGNDRMVDdDIiwibGljZW5zZWVOYW1lIjoiVmxhZGlzbGF2IEtvdmFsZW5rbyIsImFzc ...
- GeneXus笔记本—常用函数(中)
这篇文章是接着上一篇 常用函数(上)来写的 上次写到了Format 这个函数 我们继续接着这个往下来好了(づ ̄ 3 ̄)づ 还是一样 函数列表在此 https://wiki.genexus.com/c ...
- repquota - 文件系统配额的汇总
SYNOPSIS(总览) repquota [ -vugs ] filesystem... repquota [ -avugs ] DESCRIPTION(描述) repquota 显示与配额文件相关 ...
- zabbix基础之环境搭建
zabbix入门 环境部署 安装mysql #安装MySQL,官方的MySQL的repo源地址:http://repo.mysql.com/ #选择指定的MySQL版本,我这里选mysql5.7的版本 ...
- 初学Java 九九乘法表
public class MultiplicationTable { public static void main(String[] args) { System.out.println(" ...
- KMP,Trie,AC自动机题目集
字符串算法并不多,KMP,trie,AC自动机就是其中几个最经典的.字符串的题目灵活多变也有许多套路,需要多做题才能体会.这里收集了许多前辈的题目做个集合,方便自己回忆. KMP题目:https:// ...