不同对象中 类型与属性名的属性 进行数据转换
发布时间:2020-12-15 08:24:32 所属栏目:Java 来源:网络整理
导读:1 package com.xnky.pams.common.utils; 2 3 import org.slf4j.Logger; 4 import org.slf4j.LoggerFactory; 5 6 import java.lang.reflect.Field; 7 import java.lang.reflect.Method; 8 import java.lang.reflect.ParameterizedType; 9 import java.lang.re
1 package com.xnky.pams.common.utils; 2 3 import org.slf4j.Logger; 4 import org.slf4j.LoggerFactory; 5 6 import java.lang.reflect.Field; 7 import java.lang.reflect.Method; 8 import java.lang.reflect.ParameterizedType; 9 import java.lang.reflect.Type; 10 import java.math.BigDecimal; 11 import java.util.ArrayList; 12 import java.util.Collection; 13 import java.util.Date; 14 import java.util.HashMap; 15 import java.util.HashSet; 16 import java.util.List; 17 import java.util.Map; 18 import java.util.Set; 19 import java.util.concurrent.ConcurrentHashMap; 20 21 22 /** 23 * 把对象A中属性的值传给对象B相同类型的属性。 24 * 25 * @author Feng Yongkang,2019/8/6 26 * @version v1.0 27 */ 28 public class PojoConvertUtil { 29 private static Logger logger = LoggerFactory.getLogger(PojoConvertUtil.class); 30 /** 31 * 变量缓存. 32 */ 33 private static final Map<String,Map<String,Field>> CACHE_FIELDS = new ConcurrentHashMap<>(); 34 private static final Set<Class> BASIC_CLASS = new HashSet<>(); 35 36 static { 37 BASIC_CLASS.add(Integer.class); 38 BASIC_CLASS.add(Character.class); 39 BASIC_CLASS.add(Byte.class); 40 BASIC_CLASS.add(Float.class); 41 BASIC_CLASS.add(Double.class); 42 BASIC_CLASS.add(Boolean.class); 43 BASIC_CLASS.add(Long.class); 44 BASIC_CLASS.add(Short.class); 45 BASIC_CLASS.add(String.class); 46 BASIC_CLASS.add(BigDecimal.class); 47 } 48 49 private PojoConvertUtil() { 50 } 51 52 /** 53 * 将具有相同属性的类型进行转换. 54 * 55 * @param orig 原始对象 56 * @param targetClass 目标对象 57 * @param <T> 泛型 58 * @return 泛型 59 */ 60 public static <T> T convertPojo(Object orig,Class<T> targetClass) { 61 try { 62 T target = targetClass.newInstance(); 63 /** 获取源对象的所有变量 */ 64 Field[] fields = orig.getClass().getDeclaredFields(); 65 for (Field field : fields) { 66 if (isStatic(field)) { 67 continue; 68 } 69 /** 获取目标对象与原对象相同的字段 */ 70 Field targetField = getTargetField(targetClass,field.getName()); 71 if (targetField == null) { 72 continue; 73 } 74 /*获取原对象中字段的值*/ 75 Object value = getFiledValue(field,orig); 76 if (value == null) { 77 continue; 78 } 79 Class type1 = field.getType(); 80 Class type2 = targetField.getType(); 81 //两个类型是否相同 82 boolean sameType = type1.equals(type2); 83 if (isBasicType(type1)) { 84 if (sameType) { 85 setFieldValue(targetField,target,value); 86 } 87 } else if (value instanceof Map && Map.class.isAssignableFrom(type2)) {//对map 88 setMap((Map) value,field,targetField,target); 89 } else if (value instanceof Set && Set.class.isAssignableFrom(type2)) {//对set 90 setCollection((Collection) value,target); 91 } else if (value instanceof List && List.class.isAssignableFrom(type2)) {//对list 92 setCollection((Collection) value,target); 93 } else if (value instanceof Enum && Enum.class.isAssignableFrom(type2)) {//对enum 94 setEnum((Enum) value,target); 95 } else if (value instanceof java.util.Date 96 && java.util.Date.class.isAssignableFrom(type2)) {//对日期类型,不处理如joda包之类的扩展时间,不处理calendar 97 setDate((Date) value,type2,sameType); 98 } 99 } 100 return target; 101 } catch (Throwable t) { 102 logger.error("转换失败:" + t.getMessage()); 103 throw new RuntimeException(t.getMessage()); 104 } 105 } 106 107 /** 108 * 获取字段值. 109 * 110 * @param field 111 * @param obj 112 * @return 113 */ 114 private static Object getFiledValue(Field field,Object obj) throws IllegalAccessException { 115 //获取原有的访问权限 116 boolean access = field.isAccessible(); 117 try { 118 //设置可访问的权限 119 field.setAccessible(true); 120 return field.get(obj); 121 } finally { 122 //恢复访问权限 123 field.setAccessible(access); 124 } 125 } 126 127 /** 128 * 设置属性值. 129 * 之所以这里用对象 对象的方法 和要传入的值 ,前两者都是一个对象里面的内容,对于这个方法来说,对象类型是不确定的。 130 * 131 * @param field 132 * @param obj 133 * @param value 134 * @throws IllegalAccessException 135 */ 136 private static void setFieldValue(Field field,Object obj,Object value) throws IllegalAccessException { 137 //获取原有的访问权限 138 boolean access = field.isAccessible(); 139 try { 140 //设置可访问的权限 141 field.setAccessible(true); 142 field.set(obj,value); 143 } finally { 144 //恢复访问权限 145 field.setAccessible(access); 146 } 147 } 148 149 /** 150 * 转换list. 151 * 152 * @param orig 原始list 153 * @param targetClass 目标list 154 * @param <T> 泛型 155 * @return 泛型 156 */ 157 public static <T> List<T> convertPojos(List orig,Class<T> targetClass) { 158 List<T> list = new ArrayList<>(orig.size()); 159 for (Object object : orig) { 160 list.add(convertPojo(object,targetClass)); 161 } 162 return list; 163 } 164 165 /** 166 * 设置Map. 167 * 168 * @param value 要转换的数据 169 * @param origField 原对象的字段 170 * @param targetField 目标对象的字段 171 * @param targetObject 目标对象 172 * @param <T> 泛型 173 */ 174 private static <T> void setMap(Map value,Field origField,Field targetField 175,T targetObject) throws IllegalAccessException,InstantiationException { 176 Type origType = origField.getGenericType(); 177 Type targetType = targetField.getGenericType(); 178 if (origType instanceof ParameterizedType && targetType instanceof ParameterizedType) {//泛型类型 179 ParameterizedType origParameterizedType = (ParameterizedType) origType; 180 Type[] origTypes = origParameterizedType.getActualTypeArguments(); 181 ParameterizedType targetParameterizedType = (ParameterizedType) targetType; 182 Type[] targetTypes = targetParameterizedType.getActualTypeArguments(); 183 if (origTypes != null && origTypes.length == 2 && targetTypes != null && targetTypes.length == 2) { 184 Class clazz = (Class) origTypes[1]; 185 if (!isBasicType(clazz) && !clazz.equals(targetTypes[1])) {//如果不是基本类型并且泛型不一致,则需要继续转换 186 Set<Map.Entry> entries = value.entrySet(); 187 Map targetMap = value.getClass().newInstance(); 188 for (Map.Entry entry : entries) { 189 targetMap.put(entry.getKey(),convertPojo(entry.getValue(),(Class) targetTypes[1])); 190 } 191 setFieldValue(targetField,targetObject,targetMap); 192 return; 193 } 194 } 195 } 196 setFieldValue(targetField,value); 197 } 198 199 /** 200 * 设置集合. 201 * 202 * @param value 203 * @param origField 204 * @param targetField 205 * @param targetObject 206 * @param <T> 207 * @throws IllegalAccessException 208 * @throws InstantiationException 209 */ 210 private static <T> void setCollection(Collection value,Field targetField 211,InstantiationException { 212 Type origType = origField.getGenericType(); 213 Type targetType = targetField.getGenericType(); 214 if (origType instanceof ParameterizedType && targetType instanceof ParameterizedType) {//泛型类型 215 ParameterizedType origParameterizedType = (ParameterizedType) origType; 216 Type[] origTypes = origParameterizedType.getActualTypeArguments(); 217 ParameterizedType targetParameterizedType = (ParameterizedType) targetType; 218 Type[] targetTypes = targetParameterizedType.getActualTypeArguments(); 219 //正常泛型,查看第二个泛型是否不为基本类型 220 if (origTypes != null && origTypes.length == 1 && targetTypes != null && targetTypes.length == 1) { 221 Class clazz = (Class) origTypes[0]; 222 if (!isBasicType(clazz) && !clazz.equals(targetTypes[0])) {//如果不是基本类型并且泛型不一致,则需要继续转换 223 Collection collection = value.getClass().newInstance(); 224 for (Object obj : value) { 225 collection.add(convertPojo(obj,(Class) targetTypes[0])); 226 } 227 setFieldValue(targetField,collection); 228 return; 229 } 230 } 231 } 232 setFieldValue(targetField,value); 233 } 234 235 /** 236 * 设置枚举类型. 237 * 238 * @param value 239 * @param origField 240 * @param targetField 241 * @param targetObject 242 * @param <T> 243 */ 244 private static <T> void setEnum(Enum value,Field targetField,T targetObject) throws Exception { 245 if (origField.equals(targetField)) { 246 setFieldValue(targetField,value); 247 } else { 248 //枚举类型都具有一个static修饰的valueOf方法 249 Method method = targetField.getType().getMethod("valueOf",String.class); 250 setFieldValue(targetField,method.invoke(null,value.toString())); 251 } 252 } 253 254 /** 255 * 设置日期类型. 256 * 257 * @param value 258 * @param targetField 259 * @param targetFieldType 260 * @param targetObject 261 * @param <T> 262 */ 263 private static <T> void setDate(Date value,Class targetFieldType 264,T targetObject,boolean sameType) throws IllegalAccessException { 265 Date date = null; 266 if (sameType) { 267 date = value; 268 } else if (targetFieldType.equals(java.sql.Date.class)) { 269 date = new java.sql.Date(value.getTime()); 270 } else if (targetFieldType.equals(java.util.Date.class)) { 271 date = new Date(value.getTime()); 272 } else if (targetFieldType.equals(java.sql.Timestamp.class)) { 273 date = new java.sql.Timestamp(value.getTime()); 274 } 275 setFieldValue(targetField,date); 276 } 277 278 /** 279 * 获取适配方法. 280 * 把目标类全部字段放到map中,并把这把map放入CACHE_FIELDS。 281 * 282 * @param clazz 类型 283 * @param fieldName 字段名 284 * @return 目标类型中与原对象属性名一致的字段 285 */ 286 public static Field getTargetField(Class clazz,String fieldName) { 287 String classKey = clazz.getName(); 288 //如果下次再来查找同一个类的所有字段,可以在CACHE_FIELDS找之前存过的包含该类型多有字段的map 289 Map<String,Field> fieldMap = CACHE_FIELDS.get(classKey); 290 if (fieldMap == null) { 291 fieldMap = new HashMap<>(); 292 Field[] fields = clazz.getDeclaredFields(); 293 for (Field field : fields) { 294 if (isStatic(field)) { 295 continue; 296 } 297 fieldMap.put(field.getName(),field); 298 } 299 CACHE_FIELDS.put(classKey,fieldMap); 300 } 301 return fieldMap.get(fieldName); 302 } 303 304 /** 305 * 判断是否为基础类型. 306 * 307 * @param clazz 类型 308 * @return true是 false 否 309 */ 310 public static boolean isBasicType(Class clazz) { 311 return clazz.isPrimitive() || BASIC_CLASS.contains(clazz); 312 } 313 314 /** 315 * 判断变量是否有静态修饰符static. 316 * 317 * @param field 要判断的字段 318 * @return 是否有静态修饰 319 */ 320 public static boolean isStatic(Field field) { 321 return (8 & field.getModifiers()) == 8; 322 } 323 } ? /* (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |