将之前学的Java知识进行汇总和整理,本篇主要讲述Java反射和使用用例。

项目开发中,经常遇到需要给实例化对象设置属性值,并且当属性特别多时,setter属性占用很大篇幅,在此用反射实现实例化对象,并自动设置属性值。可以作为以后项目的小工具,方便开发。

大致思路:(1)对需要实例化的Class对象,通过反射进行实例化;(2)将固定格式的参数注入到对象中。

篇外话:该思路与Spring的IOC类似,(1)程序启动时,Spring会解析提前配置好的Bean信息(如通过XML配置或注解配置),将Bean抽象为BeanDefinition结构,其中包含类的全限定名和依赖的类信息,并注册到容器中(说白了就是key-value的map中)。(2)在程序第一次执行getBean()时,会注入依赖的对象,这个会设计级联注入,直到属性为基本类型。


 

开始正文,下边代码是实现了类的实例化和属性设置功能,主要包括 简单数据类型设置 和 级联对象引用设置。

(1)创建类实例化工厂类:包含实例化和设置属性值两个步骤;

(2)StringUtils类用于处理setter和getter方法名

(3)BeanUtils类用于设置属性,其中包含级联属性实例化

具体过程已记录在代码注释中。

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

public class ClassInstanceFactory{
    private  ClassInstanceFactory(){}

    /**
     * 1.首先进行实例化;2.再对实例化对象设置属性值,格式“属性:值|属性:值”
     * @param clazz Class反射实例化
     * @param value 为实例化对象设置属性值
     * @param <T>
     * @return
     */
    public static <T> T createInstane(Class<T> clazz, String value){
        try {
            Object obj = clazz.getDeclaredConstructor().newInstance();
            BeanUtils.setValue(obj, value);
            return (T)obj;
        } catch (Exception e){
             return null;
        }
    }
}

class StringUtils{
    /**
     * 首字母大写,以获取setter和getter方法
     * @param str
     * @return
     */
    public static String initCap(String str){
        if(null == str || "".equals(str)){
            return  str;
        }
        if(str.length() == 1){
            return str.toUpperCase();
        } else{
            return str.substring(0,1).toUpperCase()+str.substring(1);
        }
    }
}

//为实例化对象设置属性值
class BeanUtils{
    public static void setValue(Object obj, String value){
        String[] attrs = value.split("\\|");
        for(int i = 0; i < attrs.length; i++){
            String[] attr = attrs[i].split("\\:");
            //判断是否是处理级联引用
            if(attr[0].contains(".")) {
                String[] str = attr[0].split("\\.");
               try {
                   //1.获取级联属性是否为null
                   Method getMethod = obj.getClass().getDeclaredMethod("get" + StringUtils.initCap(str[0]));
                   Object tmp = getMethod.invoke(obj);

                   if(tmp == null){
                       //2.为null时,需要初始化后,再设置属性值
                       //2.1 首先实例化
                       Field field = obj.getClass().getDeclaredField(str[0]);
                       tmp = field.getType().getDeclaredConstructor().newInstance();
                       //2.2 设置级联引用的属性
                       setValue(tmp, attrs[i].substring(attrs[i].indexOf(".")+1));
                       //2.3 将实例化完成的级联属性设置到对象中
                       Method method = obj.getClass().getDeclaredMethod("set" + StringUtils.initCap(str[0]), field.getType());
                       method.invoke(obj, tmp);
                   } else {
                       //3.不为空时,直接设置级联引用的属性
                      setValue(tmp, attrs[i].substring(attrs[i].indexOf(".")+1));
                   }
               } catch (Exception e){

               }
            } else {
                //非级联引用
                try {
                    //getField返回所有public的属性;       getDeclaredField 返回类所有声明的属性
                    Field field = obj.getClass().getDeclaredField(attr[0]);
                    //getMethod 返回所有public的方法,包含父类    getDeclaredMethod返回所有声明的方法,不包含父类
                    Method method = obj.getClass().getDeclaredMethod("set" + StringUtils.initCap(attr[0]), field.getType());
                    //获取属性实际值
                    Object val = convertType(field.getType().getName(), attr[1]);
                    method.invoke(obj, val);
                } catch (Exception e) {

                }
            }

        }

    }

    private static Object convertType(String type, String value){
        if(Integer.class.getName().equals(type) || "int".equals(type)) {
            return Integer.valueOf(value);
        } else if(Double.class.getName().equals(type) || "double".equals(type)){
            return Double.valueOf(value);
        } else if(Long.class.getName().equals(type) || "long".equals(type)){
            return Long.valueOf(value);
        } else if(Date.class.getName().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;
        }
    }
}

测试:

/**
 * 对简单对象进行实例化,并给各属性赋值
 * 为避免大量setter代码出现,使用反射机制简化初始化过程
 */
public class ReflectAndSimplObject {

    public static void main(String[] args){
        String value = "name:bob|age:80|birth:1990-10-10|dept.name:ssc|dept.company.name:td|dept.company1.name:ry";
        Person p = ClassInstanceFactory.createInstane(Person.class, value);
        System.out.println(p);
    }
}

class Company{
    String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Company{" +
                "name='" + name + '\'' +
                '}';
    }
}

class Company1 {
    String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Company1{" +
                "name='" + name + '\'' +
                '}';
    }
}

class Dept{
    String name;
    long id;
    Company company;
    Company1 company1;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Company getCompany() {
        return company;
    }

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

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public Company1 getCompany1() {
        return company1;
    }

    public void setCompany1(Company1 company1) {
        this.company1 = company1;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", company=" + company +
                ", company1=" + company1 +
                '}';
    }
}



class Person{
    String name;
    int age;
    Date birth;
    Dept dept;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    public Dept getDept() {
        return dept;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", birth=" + birth +
                ", dept=" + dept +
                '}';
    }
}

 

输出:

Person{name='bob', age=80, birth=Wed Oct 10 00:00:00 CST 1990, dept=Dept{name='ssc', id=0, company=Company{name='td'}, company1=Company1{name='ry'}}}

总结

反射的使用,将增加代码的灵活性,并使代码编写更简洁。可以将这个作为以后项目的工具,简化diamagnetic编写。