Java的父子类型相互赋值

167 阅读2分钟

现在项目都是前后端分离,项目中一般也要求前端不写逻辑,所以前端的小伙伴一般都要后端的输出能直接用,即使状态名称、性别名称之类的数据也要后端和数据一次性给前端。而对于后端来说,从数据库中取出来的数据类model(有的叫pojo或者entity或者其他)只会有状态编码,是不会有状态名称的,所以需要重新组装一个新的类,这也是VO的主要作用。

比如Student类

@Data
public class Student {
    // 主键ID
    private Integer id;
    // 姓名
    private String name;
    // 年龄
    private Integer age;
    // 性别 0 未知 1 男 2 女
    private Integer gender;
    // 状态 0 无效数据 1 有效数据
    private Integer status;
}

输出的VO为 StudentVo

@Data
public class StudentVO {
    // 主键ID
    private Integer id;
    // 姓名
    private String name;
    // 年龄
    private Integer age;
    // 性别 0 未知 1 男 2 女
    private Integer gender;
    // 性别名称
    private String genderName
    // 状态 0 无效数据 1 有效数据
    private Integer status;
    // 状态名称
    private String statusName;
}

或者定义为

@Data
public class StudentVO extends Student {
    // 性别名称
    private String genderName;
    // 状态名称
    private String statusName;
}

按以上例子把Student的数据赋值给StudentVo可能需要如下操作:

    Student student = studentService.get(id);
    StudentVO studentVo = new StudentVo();
    studentVo.setId(student.getId());
    studentVo.setName(student.getName());
    studentVo.setAge(student.getAge());
    studentVo.setGender(student.getGender());
    studentVo.setStatus(student.getStatus());
    studentVo.setGenderName(...);
    studentVo.setStatusName(...);

显然,如果数据过多这样会比较麻烦,有一些其他办法输出或者转换,比如转换成Map格式,再put添加genderNamestatusName

如果按照第二种方式使用VO的话,因为Student和StudentVo是父子关系,可以采用以下方式转换:

    public static <T> T superToObj(Object superObj, Class<T> clazz)
            throws ReflectiveOperationException {
        Class<?> clsOrig = superObj.getClass();
        T t = clazz.newInstance();

        for (Field field : clsOrig.getDeclaredFields()) {
            field.setAccessible(true);
            Object value = field.get(superObj);

            field.set(t, value);
        }
        return t;
    }

以上方法要求两个类必须是父子关系,并且不支持子类对父类的赋值

StudentVo studentVo = superToObject(student, StudentVo.class);

如果是子类对父类的赋值,可以用类型转换:

Student student = (Student)stduentVo;

附:Object转Map的方法:

    /**
     * Object类型数据转成Map结构
     * @param object 任意类的对象
     * @return map结构数据
     * @throws IllegalAccessException
     */
    public static Map<String, Object> objectToMap(Object object)
            throws IllegalAccessException {
        Map<String, Object> map = new HashMap<>();
        Class<?> cla = object.getClass();
        Field[] fields = cla.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            String keyName = field.getName();
            Object value = field.get(object);
            map.put(keyName, value);
        }
        return map;
    }

当然,如果允许的话,比较省事的方法是直接把model定义成Vo形式的数据,从数据库中取到值之后,直接set说明字段就行了。