Java学习笔记——属性自动设置(单级和级联)

属性自动设置

属性设置建议采用字符串的形式来描述对应的类型。
1、采用“属性:内容|属性:内容|”的形式来为简单Java类中的属性初始化。

2、类设计的基本结构:应该由一个专门的ClassInstanceFactory类负责所有的反射处理,即:接收反射对象与要设置的反射内容,同时可以获取指定类的实例化对象在这里插入图片描述
3、设计的基本结构:

package demo;

public class JavaAPIDemo {
	public static void main(String[] args) throws Exception {
		String value = "ename:Smithi|job:Clerk" ;
		Emp emp = ClassInstanceFactory.create(Emp.class, value);
		System.out.println("姓名:" + emp.getEname() + "、职位:" + emp.getJob());
		
	}
}
class ClassInstanceFactory{
	private ClassInstanceFactory() {}
	/**
	 * 实例化对象的创建方法,该对象可以根据传入的字符串结构“属性:内容|属性:内容”
	 * @param <T>
	 * @param clazz 要进行反射实例化的Class类对象,有Class就可以反射实例化对象
	 * @param value	要设置给对象的属性内容
	 * @return	一个已经配置好属性内容的Java类对象
	 */
	public static <T> T create(Class<?> clazz, String value) {
		return null;
	}
}
class Emp{
	private String ename;
	private String job;
	public String getEname() {
		return ename;
	}
	public void setEname(String ename) {
		this.ename = ename;
	}
	public String getJob() {
		return job;
	}
	public void setJob(String job) {
		this.job = job;
	}

	
}

要留给用户完善的就是ClassInstanceFactory.create()处理方法。

单级属性配置

对于此时的Emp类里面会发现所给出的数据类都没有其它的引用关联了,至少描述了Emp的本类的对象,这样的设置称为单级设置处理,所以此时应该处理两件事:

  • 需要通过反射进行指定类对象的实例化处理;
  • 进行内容的设置(Field属性类型、方法名称、要设置的内容);
  • 在这里插入图片描述
    1、定义String类实现首字母大写
class StringUtils{
	public static String initcap(String str) {
		if(str == null || "".equals(str)) {
			return str;
		}
		if(str.length()==1) {
			return str.toUpperCase();
		}else {
			return str.substring(0,1).toUpperCase() + str.substring(1);
		}
	}
}

2、定义BeanUtils工具类,该工具类主要实现属性的设置。

class BeanUtils{
	private BeanUtils() {}
	/**
	 * 实现指定对象的属性设置
	 * @param obj	要进行反射操作的实例化对象
	 * @param value	包含有指定内容的字符串,格式“属性:内容|属性:内容”
	 */
	public static void setValue(Object obj, String value) {
		String results [] = value.split("\\|");//按照“|”进行分组拆分
		for(int x=0; x< results.length;x++) {//循环设置属性内容
			//attval[0]保存的是属性名称、attval[1]保存的是属性内容
			String attval[] = results[x].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) {
				
			}
		}
	}
}

3、ClassInstanceFactory负责实例化对象并且调用BeanUtils类实现属性内容的设置。

class ClassInstanceFactory{
	private ClassInstanceFactory() {}
	/**
	 * 实例化对象的创建方法,该对象可以根据传入的字符串结构“属性:内容|属性:内容”
	 * @param <T>
	 * @param clazz 要进行反射实例化的Class类对象,有Class就可以反射实例化对象
	 * @param value	要设置给对象的属性内容
	 * @return	一个已经配置好属性内容的Java类对象
	 */
	public static <T> T create(Class<?> clazz, String value) {
		//如果要想采用反射机型简单Java类对象属性设置的时候,类中必须要有无参构造
		try {
			Object obj = clazz.getDeclaredConstructor().newInstance();
			BeanUtils.setValue(obj, value);//通过反射设置属性
			return  (T) obj;//返回对象
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} 
	}
}

即使现在类中的属性再多,那么也可以轻松实现setter的调用(类对象实例化处理)

设置多种数据类型

在一般的实际开发之中面对java类中的属性类型一般可选为:long(Long)、int(Integer)、double(Double)、String、Date(日期、日期时间),所以当前的程序代码就必须做出修改,要求可以实现各种数据类型的配置。

package demo;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class JavaAPIDemo {
	public static void main(String[] args) throws Exception {
		String value = "empno:940525|ename:Smithi|job:Clerk|salary:9999.88|hiredate:1994-05-25" ;
		Emp emp = ClassInstanceFactory.create(Emp.class, value);
		System.out.println("工号:"+emp.getEmpno()+"姓名:" + emp.getEname() + "、职位:" + emp.getJob()+"、薪水:" + emp.getSalary()+"、雇佣日期:" + emp.getHiredate());
		
	}
}
class ClassInstanceFactory{
	private ClassInstanceFactory() {}
	/**
	 * 实例化对象的创建方法,该对象可以根据传入的字符串结构“属性:内容|属性:内容”
	 * @param <T>
	 * @param clazz 要进行反射实例化的Class类对象,有Class就可以反射实例化对象
	 * @param value	要设置给对象的属性内容
	 * @return	一个已经配置好属性内容的Java类对象
	 */
	public static <T> T create(Class<?> clazz, String value) {
		//如果要想采用反射机型简单Java类对象属性设置的时候,类中必须要有无参构造
		try {
			Object obj = clazz.getDeclaredConstructor().newInstance();
			BeanUtils.setValue(obj, value);//通过反射设置属性
			return  (T) obj;//返回对象
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} 
	}
}
class StringUtils{
	public static String initcap(String str) {
		if(str == null || "".equals(str)) {
			return str;
		}
		if(str.length()==1) {
			return str.toUpperCase();
		}else {
			return str.substring(0,1).toUpperCase() + str.substring(1);
		}
	}
}
class BeanUtils{
	private BeanUtils() {}
	/**
	 * 实现指定对象的属性设置
	 * @param obj	要进行反射操作的实例化对象
	 * @param value	包含有指定内容的字符串,格式“属性:内容|属性:内容”
	 */
	public static void setValue(Object obj, String value) {
		String results [] = value.split("\\|");//按照“|”进行分组拆分
		for(int x=0; x< results.length;x++) {//循环设置属性内容
			//attval[0]保存的是属性名称、attval[1]保存的是属性内容
			String attval[] = results[x].split(":");//获取“属性名称”与内容
			try {
				Field field = obj.getClass().getDeclaredField(attval[0]);//获取成员
				Method setMethod = obj.getClass().getDeclaredMethod("set"+StringUtils.initcap(attval[0]), field.getType());
				Object convertValue = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
				setMethod.invoke(obj, convertValue);//调用setter 方法设置内容
				}catch(Exception e) {			
			}
		}
	}
	/**
	 * 实现属性类型转换处理
	 * @param type	属性类型,通过Field获取
	 * @param value	属性 的内容,传入的都是字符串,需要将其转变为指定类型
	 * @return 转换后的数据
	 */
	private static Object convertAttributeValue(String type,String value) {
//		System.out.println("type =" + type + "、value=" + value);
		if("long".equals(type)|| "java.lang.Long".equals(type)) {
			return Long.parseLong(value);
		}else if("int".equals(type)||"java.lang.int".equals(type)) {
			return Integer.parseInt(value);
		}else if("double".equals(type)||"java.lang.double".equals(type)) {
			return Double.parseDouble(value);
		}else if("java.util.Date".equals(type)) {
			SimpleDateFormat sdf = null;
			if(value.matches("\\d{4}-\\d{2}-\\d{2}")) {
				sdf = new SimpleDateFormat("yyyy-MM-dd");
			}else if(value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {
				sdf = new SimpleDateFormat("yyyy-MM-DD HH:mm:ss");
			}else {
				return new Date();//当前日期
			}
			try {
				return sdf.parse(value);
				}catch(ParseException e){
					return new Date();
				}
		}else {
			return value;
		}
	}
}
class Emp{
	private long empno;
	private String ename;
	private String job;
	private double salary;
	private Date hiredate;
	public String getEname() {
		return ename;
	}
	public void setEname(String ename) {
		this.ename = ename;
	}
	public String getJob() {
		return job;
	}
	public void setJob(String job) {
		this.job = job;
	}
	public Long getEmpno() {
		return empno;
	}
	public void setEmpno(long empno) {
		this.empno = empno;
	}
	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;
	}

	
}

级联对象实例化

在给定的类对象之中存在有其它的引用的级联关系的情况下,成为多级设置。例如:一个雇员属于一个部门,一个部门属于一个公司。所以这时候简单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;
	}
}

如果要通过Emp进行操作,则应该使用“.”作为级联关系的处理:

dept.dname:财务部Emp类实例化对象.getDept().setName(“财务部”)
dept.company.name:MLDNEmp实例化类对象.getDept().getCompany().setName(“MLDN”)

考虑到代码的简洁性,应该考虑可以通过级联的配置自动实现类中属性的实例化。
现在的属性存在有多级的关系,必须与单级的配置区分开。

class BeanUtils {
	private BeanUtils() {
	}
	/**
	 * 实现指定对象的属性设置
	 * @param obj	要进行反射操作的实例化对象
	 * @param value	包含有指定内容的字符串,格式“属性:内容|属性:内容”
	 */
	public static void setValue(Object obj, String value) {
		String results [] = value.split("\\|");//按照“|”进行分组拆分
		for(int x=0; x< results.length;x++) {//循环设置属性内容
			//attval[0]保存的是属性名称、attval[1]保存的是属性内容
			String attval[] = results[x].split(":");//获取“属性名称”与内容
			try {
				if(attval[0].contains(".")) {//多级配置
					String temp[] = attval[0].split("\\.");
					Object currentObject = obj;
//					System.out.println(Arrays.toString(temp));
					//最后一位肯定是指定类中的属性名称,所以不在本次实例化处理的范围内
					for(int y = 0; y < temp.length - 1;y++) {
						System.out.println(temp[y]);
						//调用相应的getter方法,如果getter方法返回了null表示该对象未实例化
						Method getMethod = currentObject.getClass().getDeclaredMethod("get"+StringUtils.initcap(temp[y]));
						Object tempObject = getMethod.invoke(currentObject);
						if(tempObject == null) {//该对象现在并没有被实例化
							Field field = currentObject.getClass().getDeclaredField(temp[y]);//获取属性类型
							Method method = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[y]), field.getType());
							Object newObject = field.getType().getDeclaredConstructor().newInstance();
							method.invoke(currentObject, newObject);
							currentObject = newObject;
						}else {
							currentObject = tempObject;
						}
//						System.out.println(temp[y] + "--" + currentObject);
					}
				}else {
					Field field = obj.getClass().getDeclaredField(attval[0]);//获取成员
					Method setMethod = obj.getClass().getDeclaredMethod("set"+StringUtils.initcap(attval[0]), field.getType());
					Object convertValue = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
					setMethod.invoke(obj, convertValue);//调用setter 方法设置内容
				}
			}catch(Exception e) {	
			}				
		}
	}

	/**
	 * 实现属性类型转换处理
	 * 
	 * @param type  属性类型,通过Field获取
	 * @param value 属性 的内容,传入的都是字符串,需要将其转变为指定类型
	 * @return 转换后的数据
	 */
	private static Object convertAttributeValue(String type, String value) {
//		System.out.println("type =" + type + "、value=" + value);
		if ("long".equals(type) || "java.lang.Long".equals(type)) {
			return Long.parseLong(value);
		} else if ("int".equals(type) || "java.lang.int".equals(type)) {
			return Integer.parseInt(value);
		} else if ("double".equals(type) || "java.lang.double".equals(type)) {
			return Double.parseDouble(value);
		} else if ("java.util.Date".equals(type)) {
			SimpleDateFormat sdf = null;
			if (value.matches("\\d{4}-\\d{2}-\\d{2}")) {
				sdf = new SimpleDateFormat("yyyy-MM-dd");
			} else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {
				sdf = new SimpleDateFormat("yyyy-MM-DD HH:mm:ss");
			} else {
				return new Date();// 当前日期
			}
			try {
				return sdf.parse(value);
			} catch (ParseException e) {
				return new Date();
			}
		} else {
			return value;
		}
	}
}

级联属性设置

					//最后一位肯定是指定类中的属性名称,所以不在本次实例化处理的范围内
					for(int y = 0; y < temp.length - 1;y++) {
						System.out.println(temp[y]);
						//调用相应的getter方法,如果getter方法返回了null表示该对象未实例化
						Method getMethod = currentObject.getClass().getDeclaredMethod("get"+StringUtils.initcap(temp[y]));
						Object tempObject = getMethod.invoke(currentObject);
						if(tempObject == null) {//该对象现在并没有被实例化
							Field field = currentObject.getClass().getDeclaredField(temp[y]);//获取属性类型
							Method method = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[y]), field.getType());
							Object newObject = field.getType().getDeclaredConstructor().newInstance();
							method.invoke(currentObject, newObject);
							currentObject = newObject;
						}else {
							currentObject = tempObject;
						}
//						System.out.println(temp[y] + "--" + currentObject);
					}

当此时循环处理完成之后,currentObject表示单级ius可以进行setter方法调用的对象了,并且该对象理论上一定不为空。随后就可以按照之前的方式利用对象进行setter调用。
【范例】实现对象级联属性设置

					//进行属性内容设置
					Field field = currentObject.getClass().getDeclaredField(temp[temp.length-1]);//获取成员
					Method setMethod = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[temp.length-1]), field.getType());
					Object convertValue = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
					setMethod.invoke(currentObject, convertValue);//调用setter 方法设置内容
				}else {
					Field field = obj.getClass().getDeclaredField(attval[0]);//获取成员
					Method setMethod = obj.getClass().getDeclaredMethod("set"+StringUtils.initcap(attval[0]), field.getType());
					Object convertValue = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
					setMethod.invoke(obj, convertValue);//调用setter 方法设置内容

以后开发之中简单Java类的复制处理将不再重复嗲用setter操作完成,而这种处理形式是在正规开发之中普遍采用形式。

完整代码:

package demo;

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;

public class JavaAPIDemo {
	public static void main(String[] args) throws Exception {
		String value = "empno:940525|ename:Smithi|job:Clerk|salary:9999.88|hiredate:1994-05-25"
				+ "|dept.dname:财务部|dept.company.name:MLDN";
		Emp emp = ClassInstanceFactory.create(Emp.class, value);
		System.out.println("工号:" + emp.getEmpno() + "姓名:" + emp.getEname() + "、职位:" + emp.getJob() + "、薪水:"
				+ emp.getSalary() + "、雇佣日期:" + emp.getHiredate());
		System.out.println(emp.getDept().getDname());
		System.out.println(emp.getDept().getCompany().getName());
	}
}

class ClassInstanceFactory {
	private ClassInstanceFactory() {
	}

	/**
	 * 实例化对象的创建方法,该对象可以根据传入的字符串结构“属性:内容|属性:内容”
	 * 
	 * @param <T>
	 * @param clazz 要进行反射实例化的Class类对象,有Class就可以反射实例化对象
	 * @param value 要设置给对象的属性内容
	 * @return 一个已经配置好属性内容的Java类对象
	 */
	public static <T> T create(Class<?> clazz, String value) {
		// 如果要想采用反射机型简单Java类对象属性设置的时候,类中必须要有无参构造
		try {
			Object obj = clazz.getDeclaredConstructor().newInstance();
			BeanUtils.setValue(obj, value);// 通过反射设置属性
			return (T) obj;// 返回对象
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
}

class StringUtils {
	public static String initcap(String str) {
		if (str == null || "".equals(str)) {
			return str;
		}
		if (str.length() == 1) {
			return str.toUpperCase();
		} else {
			return str.substring(0, 1).toUpperCase() + str.substring(1);
		}
	}
}

class BeanUtils {
	private BeanUtils() {
	}
	/**
	 * 实现指定对象的属性设置
	 * @param obj	要进行反射操作的实例化对象
	 * @param value	包含有指定内容的字符串,格式“属性:内容|属性:内容”
	 */
	public static void setValue(Object obj, String value) {
		String results [] = value.split("\\|");//按照“|”进行分组拆分
		for(int x=0; x< results.length;x++) {//循环设置属性内容
			//attval[0]保存的是属性名称、attval[1]保存的是属性内容
			String attval[] = results[x].split(":");//获取“属性名称”与内容
			try {
				if(attval[0].contains(".")) {//多级配置
					String temp[] = attval[0].split("\\.");
					Object currentObject = obj;
//					System.out.println(Arrays.toString(temp));
					//最后一位肯定是指定类中的属性名称,所以不在本次实例化处理的范围内
					for(int y = 0; y < temp.length - 1;y++) {
						System.out.println(temp[y]);
						//调用相应的getter方法,如果getter方法返回了null表示该对象未实例化
						Method getMethod = currentObject.getClass().getDeclaredMethod("get"+StringUtils.initcap(temp[y]));
						Object tempObject = getMethod.invoke(currentObject);
						if(tempObject == null) {//该对象现在并没有被实例化
							Field field = currentObject.getClass().getDeclaredField(temp[y]);//获取属性类型
							Method method = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[y]), field.getType());
							Object newObject = field.getType().getDeclaredConstructor().newInstance();
							method.invoke(currentObject, newObject);
							currentObject = newObject;
						}else {
							currentObject = tempObject;
						}
					}
					//进行属性内容设置
					Field field = currentObject.getClass().getDeclaredField(temp[temp.length-1]);//获取成员
					Method setMethod = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[temp.length-1]), field.getType());
					Object convertValue = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
					setMethod.invoke(currentObject, convertValue);//调用setter 方法设置内容
				}else {
					Field field = obj.getClass().getDeclaredField(attval[0]);//获取成员
					Method setMethod = obj.getClass().getDeclaredMethod("set"+StringUtils.initcap(attval[0]), field.getType());
					Object convertValue = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
					setMethod.invoke(obj, convertValue);//调用setter 方法设置内容
				}
			}catch(Exception e) {	
			}				
		}
	}

	/**
	 * 实现属性类型转换处理
	 * 
	 * @param type  属性类型,通过Field获取
	 * @param value 属性 的内容,传入的都是字符串,需要将其转变为指定类型
	 * @return 转换后的数据
	 */
	private static Object convertAttributeValue(String type, String value) {
//		System.out.println("type =" + type + "、value=" + value);
		if ("long".equals(type) || "java.lang.Long".equals(type)) {
			return Long.parseLong(value);
		} else if ("int".equals(type) || "java.lang.int".equals(type)) {
			return Integer.parseInt(value);
		} else if ("double".equals(type) || "java.lang.double".equals(type)) {
			return Double.parseDouble(value);
		} else if ("java.util.Date".equals(type)) {
			SimpleDateFormat sdf = null;
			if (value.matches("\\d{4}-\\d{2}-\\d{2}")) {
				sdf = new SimpleDateFormat("yyyy-MM-dd");
			} else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {
				sdf = new SimpleDateFormat("yyyy-MM-DD HH:mm:ss");
			} else {
				return new Date();// 当前日期
			}
			try {
				return sdf.parse(value);
			} catch (ParseException e) {
				return new Date();
			}
		} else {
			return value;
		}
	}
}

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 empno;
	private String ename;
	private String job;
	private double salary;
	private Date hiredate;
	private Dept dept;

	public String getEname() {
		return ename;
	}

	public Dept getDept() {
		return dept;
	}

	public void setDept(Dept dept) {
		this.dept = dept;
	}

	public void setEname(String ename) {
		this.ename = ename;
	}

	public String getJob() {
		return job;
	}

	public void setJob(String job) {
		this.job = job;
	}

	public Long getEmpno() {
		return empno;
	}

	public void setEmpno(long empno) {
		this.empno = empno;
	}

	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;
	}

}

参考:https://edu.aliyun.com/lesson_1012_9059#_9059

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值