Java控_01原创工具类(001)_深度的对象非null转换工具V1.0
来源:互联网 发布:js获取url网页内容 编辑:程序博客网 时间:2024/06/03 16:17
Java控01原创工具类(001)深度的对象非null转换工具V1.0
1、目标需求
综述:任意对象及其属性(实例变量)转换为非null对象
关键点:
- 任意对象、包括集合容器
- 对象内所有属性,包括父类的属性
- 属性类型包括基本类型、枚举、自定义类、内部类、数组、常用集合容器(List、Set以及Map)
- 每个属性也需要做同样的非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的属性赋默认值,其中有两个关键点:
- 判断对象中值为null的属性
- 实例化值为null的属性
对于第一点,通过递归遍历对应类的字段来实现判断,其中需要考虑内部类、数组、集合容器。
对于第二点,首先要知道属性的类型:
- 对于普通类,通过获取构造方法进行实例化,对有参的构造方法需要先实例化对应参数,然后递归次步。
- 对于基本类型,需要根据不同了类型给出不同默认值,主要针对boolean和char。
- 对于枚举,获取第一个枚举值作为默认值,由于枚举比较特殊,也可以不进行处理。
- 对于内部类,和普通类区别在于反射出的构造方法需要传入父类对象作为参数。
- 对于集合容器,常用的即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
- Java控_01原创工具类(001)_深度的对象非null转换工具V1.0
- Java对象转换为json字符串的工具类
- 面向对象_工具类的完善
- JAVA工具类(8) --- json转换工具类(对象与json转换)
- 进制转换工具v1.0
- 一键清空格工具 V1.0的工具
- Java 对象和xml转换工具类
- json对象转换工具(java)
- 深度学习_工具
- 关于xml文件转换成java对象以及java对象转换成xml的工具类
- 日志工具类v1.0
- IP工具类v1.0
- HTMLParser工具类v1.0
- ZXing工具类v1.0
- 面向对象_静态的应用_工具类
- JAVA对象任意深度克隆clone工具类分享
- Java千百问_01基本概念(001)_什么是Java
- 工具类,Java转换
- 2016年8月7日,22岁生日
- 常量和变量
- linux 路由表设置 之 route 指令详解
- jboss: option requires an argument --c jboss启动报错
- 51nod oj 1256 1119 1013 1083 1014 1081<组合数+逆元+快速幂,DP,枚举,树状数组>
- Java控_01原创工具类(001)_深度的对象非null转换工具V1.0
- Python 文件处理
- 最快最简单的排序——桶排序
- Spark Streaming + Kafka Manager + (Kafka-spark-consumer) 组合
- 继承关系下new子类对象,会发生什么?
- Python调用Matplotlib绘制分布点并且添加标签
- 计算机概论
- 索引
- Android四大组件简单介绍