重温java知识(三十五、反射机制之十二:反射与简单Java类---级联对象实例化)

借鉴使用

package com.mydemo;

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

public class ReflectDemo {

    public static void main(String[] args) throws Exception {

        // 保存要设置的属性内容
        String value = "ename:Kangkang|job:Student|salary:8000.00|age:20|hiredate:2000-01-01|" +
                "dept.dname:财务部|dept.location:北京|dept.company.name:科技公司|" +
                "dept.company.createdate:2010-01-01";
        // 工具类自动设置
        Emp emp = ClassInstanceFactory.create(Emp.class, value);
        System.out.println(emp.toString() + "\n");                         // 对象数据
        System.out.println(emp.getDept().toString() + "\n");               // 对象不为空
        System.out.println(emp.getDept().getCompany().toString() + "\n");  // 对象不为空
    }
}

class Company {
    private String name;
    private Date createdate;

    @Override
    public String toString() {
        return "Company{" +
                "name='" + name + '\'' +
                ", createdate=" + 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 location;
    private Company company;

    @Override
    public String toString() {
        return "Dept{" +
                "dname='" + dname + '\'' +
                ", location='" + location + '\'' +
                ", company=" + company +
                '}';
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public Company getCompany() {
        return company;
    }

    public void setCompany(Company company) {
        this.company = company;
    }
}

class Emp {
    private String ename;
    private String job;
    private Double salary;
    private Integer age;
    private Date hiredate;
    private Dept dept;

    @Override
    public String toString() {
        return "Emp{" +
                "ename='" + ename + '\'' +
                ", job='" + job + '\'' +
                ", salary=" + salary +
                ", age=" + age +
                ", hiredate=" + hiredate +
                ", dept=" + dept +
                '}';
    }

    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 Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Date getHiredate() {
        return hiredate;
    }

    public void setHiredate(Date hiredate) {
        this.hiredate = hiredate;
    }

    public Dept getDept() {
        return dept;
    }

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

class ClassInstanceFactory {

    private ClassInstanceFactory() {
    }

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

            // 通过反射设置属性
            BeanUtils.setValue(object, value);

            // 返回对象
            return (T) object;

        } catch (Exception e) {
            // 设置错误返回null
            return null;
        }
    }
}

/**
 * 需要通过属性找到setter方法,
 * 所以需要提供有一个首字母大写的功能,
 * 为此定义一个字符串工具类
 */
class StringUtils {
    /**
     * 实现字符串首字母大写,如果只有一个字母则直接将此字母大写
     *
     * @param string 要转换的字符串
     * @return 大写处理结果,如果传入的字符串为空(包括空字符串)则返回null
     */
    public static String initcap(String string) {
        // 判断字符串是否为空,
        if (string == null || "".equals(string)) {
            // 为空则直接返回
            return string;
        }

        // 判断字符串长度
        if (string.length() == 1) {
            // 单个字母直接大写
            return string.toUpperCase();
        } else {
            return string.substring(0, 1).toUpperCase() + string.substring(1);
        }
    }
}

/**
 * 通过该类实现setter方法的调用并进行属性赋值
 */
class BeanUtils {
    public BeanUtils() {
    }

    /**
     * 实现指定对象的属性设置
     *
     * @param object 要进行反射操作的实例化对象
     * @param value  包含指定内容的字符串,格式为“属性:内容|属性:内容”
     */
    public static void setValue(Object object, String value) {

        // 按照“|”对每一组属性进行拆分
        String results[] = value.split("\\|");

        for (int i = 0; i < results.length; i++) {
            // attval[0]保存的是属性名称,attval[1]保存的是属性内容
            // 获取属性“名称”与“内容”
            String attval[] = results[i].split(":");
            try {

                // 多级配置
                if (attval[0].contains(".")) {
                    String temp[] = attval[0].split("\\.");
                    Object currentObject = object;
                    // 最有一位肯定是指定类中的属性名称,所以不在本次实例化处理的范畴之内
                    for (int j = 0; j < temp.length - 1; j++) {
                        // 实例化
                        // 调用相应的getter方法,如果getter方法返回了null表示该对象未实例化
                        Method getMethod = currentObject.getClass().getDeclaredMethod("get" +
                                StringUtils.initcap(temp[j]));

                        Object tempObject = getMethod.invoke(currentObject);

                        // 判断该对象是否实例化
                        if (tempObject == 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 = 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]);

                    // 调用setter方法设置内容
                    setMethod.invoke(currentObject, convertValue);
                } else {
                    // 获取成员
                    Field field = object.getClass().getDeclaredField(attval[0]);

                    Method setMethod = object.getClass().getDeclaredMethod("set" +
                            StringUtils.initcap(attval[0]), field.getType());

                    Object convertValue =
                            BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);

                    // 调用setter方法设置内容
                    setMethod.invoke(object, convertValue);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 实现属性类型转换处理
     *
     * @param type  属性类型,通过field获取的
     * @param value 属性的内容,传入的都是字符串,需要将其变为指定类型
     * @return 转换后的数据
     */
    public static Object convertAttributeValue(String type, String value) {
        // 根据属性类型判断字符串需要转换的目标类型,
        // 所有的类型都可以通过Object保存
        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.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 (Exception e) {
                return new Date();
            }
        } else {
            // 返回数据
            return value;
        }
    }
}

运行结果:
Emp{ename='Kangkang', job='Student', salary=8000.0, age=20, hiredate=Sat Jan 01 00:00:00 CST 2000, dept=Dept{dname='财务部', location='北京', company=Company{name='科技公司', createdate=Fri Jan 01 00:00:00 CST 2010}}}

Dept{dname='财务部', location='北京', company=Company{name='科技公司', createdate=Fri Jan 01 00:00:00 CST 2010}}

Company{name='科技公司', createdate=Fri Jan 01 00:00:00 CST 2010}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值