Java控_01原创工具类(001)_深度的对象非null转换工具V1.0

来源:互联网 发布:js获取url网页内容 编辑:程序博客网 时间:2024/06/03 16:17

Java控01原创工具类(001)深度的对象非null转换工具V1.0

1、目标需求

综述:任意对象及其属性(实例变量)转换为非null对象

关键点:

  1. 任意对象、包括集合容器
  2. 对象内所有属性,包括父类的属性
  3. 属性类型包括基本类型、枚举、自定义类、内部类、数组、常用集合容器(List、Set以及Map)
  4. 每个属性也需要做同样的非null处理

我们在实现之前,先准备一个测试用的复杂类,包含我们上述的所有需求。为了清楚描述,我们给出具体代码和类图,如下(省略所有get、set方法):

这里写图片描述

/** *  * 测试类,包含3个内部类 *  * @author sunjie at 2016年8月3日 * */public class TestNull {    private String string1;    private Long long1;    private int int1;    private Float float1;    private Boolean boolean1;    private Character character1;    private TestNullEnum testNullEnum1;    private TestNullChlidA testNullChlidA1;    private List<TestNullChlidB> testNullChlid1;    private Map<String, TestNullChlidB> testNullChlid2;    private TestNullChlidB[] testNullChlid3;    @Override    public String toString() {        return "TestNull [string1=" + string1 + ", long1=" + long1 + ", int1=" + int1 + ", float1=" + float1                + ", boolean1=" + boolean1 + ", character1=" + character1 + ", testNullEnum1=" + testNullEnum1                + ", testNullChlidA1=" + testNullChlidA1 + ", testNullChlid1=" + testNullChlid1 + ", testNullChlid2="                + testNullChlid2 + ", testNullChlid3=" + Arrays.toString(testNullChlid3) + "]";    }    public class TestNullChlidBaseA {        private String childBaseAString1;        private int childBaseALong1;        private Boolean childABoolean2;        @Override        public String toString() {            return "TestNullChlidBaseA [childBaseAString1=" + childBaseAString1 + ", childBaseALong1="                    + childBaseALong1 + ", childABoolean2=" + childABoolean2 + "]";        }    }    public class TestNullChlidA extends TestNullChlidBaseA {        private String childAString1;        private Long childALong1;        private long childALong2;        private boolean childABoolean1;        private Boolean childABoolean2;        @Override        public String toString() {            return "TestNullChlidA [childAString1=" + childAString1 + ", childALong1=" + childALong1 + ", childALong2="                    + childALong2 + ", childABoolean1=" + childABoolean1 + ", childABoolean2=" + childABoolean2                    + ", superClass=" + super.toString() + "]";        }    }    public class TestNullChlidB {        private String childBString1;        private Float childBFloat1;        private TestNullEnum testNullEnum1;        @Override        public String toString() {            return "TestNullChlidB [childBString1=" + childBString1 + ", childBFloat1=" + childBFloat1                    + ", testNullEnum1=" + testNullEnum1 + "]";        }    }}/** *  * 枚举类 *  * @author sunjie at 2016年8月3日 * */public enum TestNullEnum implements Serializable {    ENUM_VALUE0("0", "零"),    ENUM_VALUE1("1", "一"),    ENUM_VALUE2("2", "二"),    ;    private String code;    private String name;    public String getCode() {        return code;    }    public String getName() {        return name;    }    private TestNullEnum(String code, String name) {        this.code = code;        this.name = name;    }    public static TestNullEnum getEnum(String code) {        for (TestNullEnum e : TestNullEnum.values()) {            if (e.getCode().equals(code)) {                return e;            }        }        return null;    }}

根据以上测试类,我们可以梳理出几种场景,以及想要达到的效果,如下:

01、testNull对象为null:====源对象:null====处理后:TestNull [string1=, long1=0, int1=0, float1=0.0, boolean1=false, character1=0, testNullEnum1=ENUM_VALUE0, testNullChlidA1=TestNullChlidA [childAString1=, childALong1=0, childALong2=0, childABoolean1=false, childABoolean2=false, superClass=TestNullChlidBaseA [childBaseAString1=, childBaseALong1=0, childABoolean2=false]], testNullChlid1=[], testNullChlid2={}, testNullChlid3=[]]02、testNull对象内所有属性为null:====源对象:TestNull [string1=null, long1=null, int1=0, float1=null, boolean1=null, character1=null, testNullEnum1=null, testNullChlidA1=null, testNullChlid1=null, testNullChlid2=null, testNullChlid3=null]====处理后:TestNull [string1=, long1=0, int1=0, float1=0.0, boolean1=false, character1=0, testNullEnum1=ENUM_VALUE0, testNullChlidA1=TestNullChlidA [childAString1=, childALong1=0, childALong2=0, childABoolean1=false, childABoolean2=false, superClass=TestNullChlidBaseA [childBaseAString1=, childBaseALong1=0, childABoolean2=false]], testNullChlid1=[], testNullChlid2={}, testNullChlid3=[]]03、testNull对象内List、Map中元素为null:====源对象:TestNull [string1=null, long1=null, int1=0, float1=null, boolean1=null, character1=null, testNullEnum1=null, testNullChlidA1=null, testNullChlid1=[null], testNullChlid2={key1=null}, testNullChlid3=null]====处理后:TestNull [string1=, long1=0, int1=0, float1=0.0, boolean1=false, character1=0, testNullEnum1=ENUM_VALUE0, testNullChlidA1=TestNullChlidA [childAString1=, childALong1=0, childALong2=0, childABoolean1=false, childABoolean2=false, superClass=TestNullChlidBaseA [childBaseAString1=, childBaseALong1=0, childABoolean2=false]], testNullChlid1=[TestNullChlidB [childBString1=, childBFloat1=0.0, testNullEnum1=ENUM_VALUE0]], testNullChlid2={key1=TestNullChlidB [childBString1=, childBFloat1=0.0, testNullEnum1=ENUM_VALUE0]}, testNullChlid3=[]]04、testNull对象内Array中元素为null:====源对象:TestNull [string1=null, long1=null, int1=0, float1=null, boolean1=null, character1=null, testNullEnum1=null, testNullChlidA1=null, testNullChlid1=null, testNullChlid2=null, testNullChlid3=[null]]====处理后:TestNull [string1=, long1=0, int1=0, float1=0.0, boolean1=false, character1=0, testNullEnum1=ENUM_VALUE0, testNullChlidA1=TestNullChlidA [childAString1=, childALong1=0, childALong2=0, childABoolean1=false, childABoolean2=false, superClass=TestNullChlidBaseA [childBaseAString1=, childBaseALong1=0, childABoolean2=false]], testNullChlid1=[], testNullChlid2={}, testNullChlid3=[TestNullChlidB [childBString1=, childBFloat1=0.0, testNullEnum1=ENUM_VALUE0]]]

2、实现思路

要实现非null,核心就是将值为null的属性赋默认值,其中有两个关键点:

  1. 判断对象中值为null的属性
  2. 实例化值为null的属性

对于第一点,通过递归遍历对应类的字段来实现判断,其中需要考虑内部类、数组、集合容器。

对于第二点,首先要知道属性的类型:

  1. 对于普通类,通过获取构造方法进行实例化,对有参的构造方法需要先实例化对应参数,然后递归次步。
  2. 对于基本类型,需要根据不同了类型给出不同默认值,主要针对boolean和char。
  3. 对于枚举,获取第一个枚举值作为默认值,由于枚举比较特殊,也可以不进行处理。
  4. 对于内部类,和普通类区别在于反射出的构造方法需要传入父类对象作为参数。
  5. 对于集合容器,常用的即Set、List、Map。对于Set、List,遍历所有集合并进行实例化,需要通过泛型类获取集合内元素类型。对于Map,遍历所有key,并实例化对应的value,需要通过泛型获取value的类型。

3、完整代码

完整代码链接:https://github.com/popkidorc/JavaUtils/tree/master/JavaUtil

下面直接放出完整代码,这里依赖了commons-lang.jar包的ArrayUtils类:

package com.liepin.leiting.proxy.common.util;import java.lang.reflect.Array;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Modifier;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import org.apache.commons.lang.ArrayUtils;import org.apache.log4j.Logger;import org.springframework.util.CollectionUtils;/** *  * 对象处理工具类 TODO 该类可以改为工厂,对于各种特殊类型可以方便扩展 *  * @author sunjie at 2016年11月29日 * */public class ObjectUtil {    private static final Logger catalinaLog = Logger.getLogger(ObjectUtil.class);    /**     *      * 将任意对象及对象内属性转为非null对象。深度转换,自动创建对象(对于多个构造方法的类,使用第一个能够成功的构造方法进行实例化)。     *     * @author sunjie at 2016年7月28日     *     * @param object     * @param clazz     *            对象的类,无范型     * @return     * @throws Exception     */    @SuppressWarnings("rawtypes")    public static <T> T getNotNullObject(T object, Class<T> clazz) {        return getNotNullObject(object, clazz, new ArrayList<Class>());    }    /**     *      * 将任意对象及对象内属性转为非null对象。深度转换,自动创建对象(对于多个构造方法的类,使用第一个能够成功的构造方法进行实例化)。     *     * @author sunjie at 2016年7月28日     *     * @param object     * @param clazz     *            对象的类     * @param _actualTypeClazz     *            泛型类,单范型,例如List     * @return     * @throws Exception     */    @SuppressWarnings("rawtypes")    public static <T> T getNotNullObject(T object, Class<T> clazz, Class _actualTypeClazz) {        List<Class> _actualTypeClazzes = new ArrayList<Class>();        if (null != _actualTypeClazz) {            _actualTypeClazzes.add(_actualTypeClazz);        }        return getNotNullObject(object, clazz, _actualTypeClazzes);    }    /**     *      * 将任意对象及对象内属性转为非null对象。深度转换,自动创建对象(对于多个构造方法的类,使用第一个能够成功的构造方法进行实例化)。     *     * @author sunjie at 2016年7月28日     *     * @param object     * @param clazz     *            对象的类     * @param _actualTypeClazz     *            泛型类,多范型,例如Map     * @return     * @throws Exception     */    @SuppressWarnings({ "unchecked", "rawtypes" })    public static <T> T getNotNullObject(T object, Class<T> clazz, List<Class> _actualTypeClazzes) {        try {            if (null == clazz) {                throw new Exception("clazz is NULL");            }            if (null == object) {                return ObjectUtil.getNotNullObject((T) ObjectUtil.getNewInstance(clazz, _actualTypeClazzes), clazz,                        _actualTypeClazzes);            }            if (clazz.isPrimitive()) {                return object;            }            if (clazz.isEnum()) {                return object;            }            if (clazz.isInterface()) {                return ObjectUtil.getInterfaceNotNullObject(object, clazz, _actualTypeClazzes);            }            if (clazz.isArray()) {                return ObjectUtil.getArrayNotNullObject(object, clazz, _actualTypeClazzes);            }            if (!clazz.isAnnotation() && !clazz.isInterface() && !clazz.isArray() && !clazz.equals(object.getClass())) {                throw new Exception("object.getClass() and clazz is NOT EQUAL, clazz:" + clazz + ", obejctClass:"                        + object.getClass());            }            // 获取父类字段            Field[] declaredFields = getSuperFields(clazz);            Field.setAccessible(declaredFields, true);            for (Field field : declaredFields) {                // final放过                if (Modifier.isFinal(field.getModifiers())) {                    continue;                }                Object fieldObject = field.get(object);                Class fieldClass = field.getType();                List<Class> fieldActualTypeClazzes = null;                // 判断泛型                if (field.getGenericType() instanceof ParameterizedType) {                    ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();                    fieldActualTypeClazzes = new ArrayList<Class>();                    for (Type type : parameterizedType.getActualTypeArguments()) {                        fieldActualTypeClazzes.add((Class) type);                    }                }                if (null == fieldObject) {                    fieldObject = ObjectUtil.getNewInstance(fieldClass, fieldActualTypeClazzes);                }                field.set(object, ObjectUtil.getNotNullObject(fieldObject, fieldClass, fieldActualTypeClazzes));            }        } catch (Exception e) {            catalinaLog.error("NotNullObject is ERROR , object:" + object + ", class:" + clazz                    + ", _actualTypeClazzes:" + _actualTypeClazzes, e);        }        return object;    }    @SuppressWarnings("rawtypes")    private static Field[] getSuperFields(Class clazz) {        if (null == clazz) {            return new Field[] {};        }        Field[] declaredFields = clazz.getDeclaredFields();        if (null == clazz.getSuperclass()) {            return new Field[] {};        }        Field[] superFields = getSuperFields(clazz.getSuperclass());        return (Field[]) ArrayUtils.addAll(declaredFields, superFields);    }    /**     *      * 获取interface类型的非空对象,TODO 需要自行扩展     *     * @author sunjie at 2016年7月28日     *     * @param clazz     * @param _actualType     *            泛型类型     * @return     * @throws Exception     */    @SuppressWarnings({ "rawtypes", "unchecked" })    private static <T> T getInterfaceNotNullObject(T object, Class<T> clazz, List<Class> _actualTypeClazzes)            throws Exception {        if (List.class.equals(clazz)) {            List list = (List) object;            Class actualTypeClazz = Object.class;            for (int i = 0; i < list.size(); i++) {                Object entry = list.get(i);                if (!CollectionUtils.isEmpty(_actualTypeClazzes)) {                    actualTypeClazz = _actualTypeClazzes.get(0);                }                if (null == entry) {                    entry = ObjectUtil.getNewInstance(actualTypeClazz, null);                }                entry = ObjectUtil.getNotNullObject(entry, actualTypeClazz, new ArrayList<Class>());                list.remove(i);                list.add(i, entry);            }            return object;        }        if (Map.class.equals(clazz)) {            Map map = (Map) object;            Class actualTypeClazz = Object.class;            for (Object key : map.keySet()) {                if (!CollectionUtils.isEmpty(_actualTypeClazzes) && _actualTypeClazzes.size() > 1) {                    actualTypeClazz = _actualTypeClazzes.get(1);// 取value的class                }                Object entry = map.get(key);                if (null == entry) {                    entry = ObjectUtil.getNewInstance(actualTypeClazz, null);                }                entry = ObjectUtil.getNotNullObject(entry, actualTypeClazz, new ArrayList<Class>());                map.put(key, entry);            }            return object;        }        throw new Exception("not support this interface, clazz:" + clazz);    }    /**     *      * 获取数组的非空对象,TODO 待实现     *     * @author sunjie at 2016年7月28日     *     * @param arrayObject     * @param clazz     * @param _actualTypeClazz     * @return     * @throws Exception     */    @SuppressWarnings({ "rawtypes", "unchecked" })    private static <T> T getArrayNotNullObject(T arrayObject, Class<T> clazz, List<Class> _actualTypeClazzes)            throws Exception {        Object[] objectArray = (Object[]) arrayObject;        Class arrayClass = clazz.getComponentType();        if (objectArray.length <= 0) {            return (T) Array.newInstance(arrayClass, objectArray.length);        }        for (int i = 0; i < objectArray.length; i++) {            objectArray[i] = ObjectUtil.getNotNullObject(arrayClass.cast(objectArray[i]), arrayClass);        }        return (T) objectArray;    }    /**     *      * 获取基本类型的默认值     *     * @author sunjie at 2016年7月28日     *     * @param clazz     * @return     */    @SuppressWarnings("rawtypes")    private static Object getPrimitiveDefault(Class clazz) {        if (Boolean.TYPE.equals(clazz)) {            return false;        } else if (Character.TYPE.equals(clazz)) {            return '0';        }        return 0;    }    /**     *      * 获取interface类型的默认值,TODO 需要自行扩展     *     * @author sunjie at 2016年7月28日     *     * @param clazz     * @param _actualType     *            泛型类型     * @return     * @throws Exception     */    @SuppressWarnings("rawtypes")    private static Object getInterfaceDefault(Class clazz, List<Class> _actualTypeClazzes) throws Exception {        if (List.class.equals(clazz)) {            return new ArrayList();        }        if (Map.class.equals(clazz)) {            return new HashMap();        }        throw new Exception("not support this interface, clazz:" + clazz);    }    /**     *      * 获取数组的默认值,TODO 待实现     *     * @author sunjie at 2016年7月28日     *     * @param clazz     * @param _actualType     *            泛型类型     * @return     * @throws Exception     */    @SuppressWarnings("rawtypes")    private static Object getArrayDefault(Class clazz, List<Class> _actualTypeClazzes) throws Exception {        return new ArrayList().toArray();    }    /**     *      * 获取interface类型的默认值,需要自行扩展     *     * @author sunjie at 2016年7月28日     *     * @param clazz     * @param _actualType     *            泛型类型     * @return     * @throws Exception     */    @SuppressWarnings({ "rawtypes", "unchecked" })    private static Object getEnumDefault(Class clazz) throws Exception {        Field[] declaredFields = clazz.getDeclaredFields();        for (Field field : declaredFields) {            if (clazz.equals(field.getType())) {                return Enum.valueOf(clazz, field.getName());            }        }        throw new Exception("the enum is NOT VALUE, enum:" + clazz);    }    /**     *      * 构造任意对象的空对象,深层构造     *     * @author sunjie at 2016年7月28日     *     * @param clazz     * @param _actualTypeClazz     * @return     * @throws Exception     */    @SuppressWarnings({ "rawtypes", "unchecked" })    private static Object getNewInstance(Class clazz, List<Class> _actualTypeClazzes) throws Exception {        // 基本类型        if (clazz.isPrimitive()) {            return ObjectUtil.getPrimitiveDefault(clazz);        }        // enum        if (clazz.isEnum()) {            return ObjectUtil.getEnumDefault(clazz);        }        // interface        if (clazz.isInterface()) {            return ObjectUtil.getInterfaceDefault(clazz, _actualTypeClazzes);        }        // 数组        if (clazz.isArray()) {            return ObjectUtil.getArrayDefault(clazz, _actualTypeClazzes);        }        Object object = new Object();        // 首先获取无参构造器        try {            Constructor constructor = clazz.getDeclaredConstructor();            if (null != constructor) {                object = constructor.newInstance();            }        } catch (NoSuchMethodException e1) {            // 获取InnerClass构造器            try {                Constructor constructor = clazz.getDeclaredConstructor(clazz);                if (null != constructor) {                    object = constructor.newInstance(object);                }            } catch (NoSuchMethodException e2) {                // 获取其他类型,取第一个                Constructor[] constructors = clazz.getDeclaredConstructors();                for (Constructor constructor : constructors) {                    try {                        List<Object> paramObjects = new ArrayList<Object>();                        for (Class parameterClass : constructor.getParameterTypes()) {                            paramObjects.add(ObjectUtil.getNewInstance(parameterClass, null));                        }                        // 基本类型                        if (!clazz.isPrimitive()) {                            object = constructor.newInstance(paramObjects.toArray());                            break;                        }                    } catch (Exception e3) {                        continue;// 构造失败,则用下一个构造方法继续                    }                }            }        }        return object;    }

测试类:

public static void main(String[] args) throws Exception {        System.out.println("01、testNull对象为null:");        TestNull testNull = null;        System.out.println("====源对象:" + testNull);        TestNull notNullObject = ObjectUtils.getNotNullObject(testNull, TestNull.class, null);        System.out.println("====处理后:" + notNullObject);        System.out.println("");        System.out.println("02、testNull对象内所有属性为null:");        testNull = new TestNull();        System.out.println("====源对象:" + testNull);        notNullObject = ObjectUtils.getNotNullObject(testNull, TestNull.class, null);        System.out.println("====处理后:" + notNullObject);        System.out.println("");        System.out.println("03、testNull对象内List、Map中元素为null:");        testNull = new TestNull();        List<TestNullChlidB> testNullChlid1 = new ArrayList<TestNull.TestNullChlidB>();        testNullChlid1.add(null);        testNull.setTestNullChlid1(testNullChlid1);        Map<String, TestNullChlidB> testNullChlid2 = new HashMap<String, TestNull.TestNullChlidB>();        testNullChlid2.put("key1", null);        testNull.setTestNullChlid2(testNullChlid2);        System.out.println("====源对象:" + testNull);        notNullObject = ObjectUtils.getNotNullObject(testNull, TestNull.class, null);        System.out.println("====处理后:" + notNullObject);        System.out.println("");        System.out.println("04、testNull对象内Array中元素为null:");        testNull = new TestNull();        TestNullChlidB[] testNullChlidB3 = new TestNullChlidB[1];        testNullChlidB3[0] = null;        testNull.setTestNullChlid3(testNullChlidB3);        System.out.println("====源对象:" + testNull);        notNullObject = ObjectUtils.getNotNullObject(testNull, TestNull.class, null);        System.out.println("====处理后:" + notNullObject);    }

运行结果如下,满足我们的预期:

01、testNull对象为null:====源对象:null====处理后:TestNull [string1=, long1=0, int1=0, float1=0.0, boolean1=false, character1=0, testNullEnum1=ENUM_VALUE0, testNullChlidA1=TestNullChlidA [childAString1=, childALong1=0, childALong2=0, childABoolean1=false, childABoolean2=false, superClass=TestNullChlidBaseA [childBaseAString1=, childBaseALong1=0, childABoolean2=false]], testNullChlid1=[], testNullChlid2={}, testNullChlid3=[]]02、testNull对象内所有属性为null:====源对象:TestNull [string1=null, long1=null, int1=0, float1=null, boolean1=null, character1=null, testNullEnum1=null, testNullChlidA1=null, testNullChlid1=null, testNullChlid2=null, testNullChlid3=null]====处理后:TestNull [string1=, long1=0, int1=0, float1=0.0, boolean1=false, character1=0, testNullEnum1=ENUM_VALUE0, testNullChlidA1=TestNullChlidA [childAString1=, childALong1=0, childALong2=0, childABoolean1=false, childABoolean2=false, superClass=TestNullChlidBaseA [childBaseAString1=, childBaseALong1=0, childABoolean2=false]], testNullChlid1=[], testNullChlid2={}, testNullChlid3=[]]03、testNull对象内List、Map中元素为null:====源对象:TestNull [string1=null, long1=null, int1=0, float1=null, boolean1=null, character1=null, testNullEnum1=null, testNullChlidA1=null, testNullChlid1=[null], testNullChlid2={key1=null}, testNullChlid3=null]====处理后:TestNull [string1=, long1=0, int1=0, float1=0.0, boolean1=false, character1=0, testNullEnum1=ENUM_VALUE0, testNullChlidA1=TestNullChlidA [childAString1=, childALong1=0, childALong2=0, childABoolean1=false, childABoolean2=false, superClass=TestNullChlidBaseA [childBaseAString1=, childBaseALong1=0, childABoolean2=false]], testNullChlid1=[TestNullChlidB [childBString1=, childBFloat1=0.0, testNullEnum1=ENUM_VALUE0]], testNullChlid2={key1=TestNullChlidB [childBString1=, childBFloat1=0.0, testNullEnum1=ENUM_VALUE0]}, testNullChlid3=[]]04、testNull对象内Array中元素为null:====源对象:TestNull [string1=null, long1=null, int1=0, float1=null, boolean1=null, character1=null, testNullEnum1=null, testNullChlidA1=null, testNullChlid1=null, testNullChlid2=null, testNullChlid3=[null]]====处理后:TestNull [string1=, long1=0, int1=0, float1=0.0, boolean1=false, character1=0, testNullEnum1=ENUM_VALUE0, testNullChlidA1=TestNullChlidA [childAString1=, childALong1=0, childALong2=0, childABoolean1=false, childABoolean2=false, superClass=TestNullChlidBaseA [childBaseAString1=, childBaseALong1=0, childABoolean2=false]], testNullChlid1=[], testNullChlid2={}, testNullChlid3=[TestNullChlidB [childBString1=, childBFloat1=0.0, testNullEnum1=ENUM_VALUE0]]]
1 0
原创粉丝点击