工具类篇3——反射工具类(对象反射)》

子目录

《工具类篇3——反射工具类(方法反射)》
《工具类篇3——反射工具类(对象反射)》
《工具类篇3——反射工具类(获取泛型类型)》


工具类全都是阿里代码规范与SonalLint扫描通过的,可以放心使用!

本工具包的公网Maven引用地址如下


    com.gitee.taotaojs
    comn-basic
    1.0.0

直接引用即可。
之后我也会出一个关于上传公网的踩坑手册,以及发布一下我用的CheckStyle文件检查相关异味,敬请期待!

【附上仓库地址】
阿里云的Maven仓库
sonatype仓库


注意事项:
本工具类有使用到同包下的工具类,详情请看gitee的代码,有所有工具类的代码~

import com.taotaojs.exception.MyInnerException; - 内部异常类,直接继承RuntimeException
import com.gitee.taotaojs.util.CollectionUtil; - 集合工具类
import com.gitee.taotaojs.util.ConstantUtil; - 常量类
(后期全都会在CSDN上更新的)

主要功能

  • 支持对象与Map的互转
  • 判断对象是否为空
  • 获取泛型实例
  • 以某属性为key将集合整理为Map对象的方法
  • 两个不同类型对象的相同属性拷贝,支持黑白名单与指定属性
  • 两个不同类型集合的相同属性拷贝,支持黑白名单与指定属性
  • 对象深克隆

具体代码

package com.gitee.taotaojs.util.reflect;

import com.gitee.taotaojs.exception.MyInnerException;
import com.gitee.taotaojs.util.CollectionUtil;
import com.gitee.taotaojs.util.ConstantUtil;

import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author TaoTaojs
 * @date 2019/4/28 14:56
 * 

Description

*

对象操作工具

*

简介

* 对对象进行判断、整理等一系列操作 *

主要功能:

*
    *
  1. 支持对象与Map的互转
  2. *
  3. 判断对象是否为空
  4. *
  5. 获取泛型实例
  6. *
  7. 以某属性为key将集合整理为Map对象的方法
  8. *
  9. 两个不同类型对象的相同属性拷贝,支持黑白名单与指定属性
  10. *
  11. 两个不同类型集合的相同属性拷贝,支持黑白名单与指定属性
  12. *
  13. 对象深克隆
  14. *
* 关联类: */ public final class EntityUtil { private EntityUtil(){} /** * 对象转为Map结构 * @param obj 具体对象 * @return Map结构 * @throws Exception */ public static Map obj2Map(Object obj){ Map map=new HashMap<>(ConstantUtil.TWO); PropertyDescriptor[] propertyDescriptors = ReflectUtil.getPropertyList(obj.getClass()); for (PropertyDescriptor property : propertyDescriptors) { String key = property.getName(); if (key.compareToIgnoreCase("class") == 0) { continue; } Method getter = property.getReadMethod(); if(getter != null){ map.put(key, ReflectUtil.invokeMethod(obj, getter)); } } return map; } /** * Map映射为具体对象(推荐直接使用BeanMap类) * @param map 属性数据 * @param clz 类类型 * @return 具体对象 * @throws Exception */ public static Object map2Obj(Map map, Class clz){ if (map == null) { return null; } Object obj = getInstance(clz); PropertyDescriptor[] propertyDescriptors = ReflectUtil.getPropertyList(obj.getClass()); for (PropertyDescriptor property : propertyDescriptors) { Method setter = property.getWriteMethod(); if (setter != null) { ReflectUtil.invokeMethod(obj, setter, map.get(property.getName())); } } return obj; } /** * 对象添加属性 * 使用反射获取对应属性的set方法 * @param item 对象 * @param map [属性名:值] * @param 对象泛型 * @param 属性对象泛型 * @return 添加好对象之后的属性 */ public static T addProperty(T item, Map map){ for (Map.Entry stringObjectEntry : map.entrySet()) { String key = stringObjectEntry.getKey(); ReflectUtil.invokeSet(item, key, stringObjectEntry.getValue()); } return item; } /** * 判断对象是否为空 * @param obj 对象 * @return 为空返回true */ public static boolean isEmpty(Object obj){ if(obj == null){ return true; } for (Field f : obj.getClass().getDeclaredFields()) { //公有化属性 f.setAccessible(true); //判断字段是否为空,并且对象属性中的基本都会转为对象类型来判断 if (ReflectUtil.invokeGet(obj, f) != null) { return false; } } return true; } /** * 获取两个对象中相同名称和类型的属性 * @param clazz1 类型1 * @param clazz2 类型2 * @param 泛型1 * @param 泛型2 * @return map类型的属性 */ protected static Map> getFieldList(Class clazz1, Class clazz2) { //获取所有属性 Field[] fields1 = clazz1.getDeclaredFields(); Field[] fields2 = clazz2.getDeclaredFields(); //创建Map容器 Map> fieldMap = new HashMap<>(2); for (Field f1 : fields1) { for (Field f2 : fields2) { //判断两个字段是否名称相同而且类型相同 if (f1.getName().equals(f2.getName()) && equalFieldsType(f1, f2)) { fieldMap.put(f1.getName(), f1.getType()); } } } return fieldMap; } /** * 获取一个泛型的实例 * @param clazz 类型 * @param 泛型 * @return 泛型实例 */ public static T getInstance(Class clazz) { try { return clazz.newInstance(); } catch (Exception e) { throw new MyInnerException(e); } } /** * 判断两个字段的类型是否相同 * * @param field1 复制源 * @param field2 复制目标 * @return 相同返回true */ public static boolean equalFieldsType(Field field1, Field field2) { String fTypeName1 = field1.getType().getSimpleName(); String fTypeName2 = field2.getType().getSimpleName(); //1. 处理基本数据类型和包装类 Map map = new HashMap<>(ConstantUtil.EIGHT); map.put(int.class.getSimpleName(), Integer.class.getSimpleName()); map.put(byte.class.getSimpleName(), Byte.class.getSimpleName()); map.put(short.class.getSimpleName(), Short.class.getSimpleName()); map.put(char.class.getSimpleName(), Character.class.getSimpleName()); map.put(long.class.getSimpleName(), Long.class.getSimpleName()); map.put(float.class.getSimpleName(), Float.class.getSimpleName()); map.put(double.class.getSimpleName(), Double.class.getSimpleName()); map.put(boolean.class.getSimpleName(), Boolean.class.getSimpleName()); /** * 在涉及包装类的判断逻辑中,源数据不能是包装类 * 因为包装类一旦为null,会引发异常 */ for (Map.Entry stringStringEntry : map.entrySet()) { boolean flag = stringStringEntry.getKey().equals(fTypeName2) && map.get(stringStringEntry.getKey()).equals(fTypeName1); boolean flag1 = stringStringEntry.getKey().equals(fTypeName1) && map.get(stringStringEntry.getKey()).equals(fTypeName2); if (flag1 || flag) { return true; } } //2. 类型相同 return fTypeName1.equals(fTypeName2); } /** * 以某个属性名称为key,将集合整理为Map对象(默认属性名为id) * @param clazz 类类型 * @param list 集合 * @param proName 属性名 * @param 属性名类型泛型 * @param 集合泛型 * @return map对象 */ public static Map objList2Map(Class clazz, List list, String proName){ Map map = new HashMap<>(2); Method getIdMethod = ReflectUtil.getGetMethod(clazz, proName); for (V v : list) { try { map.put((K) getIdMethod.invoke(v), v); } catch (Exception e) { throw new MyInnerException(e); } } return map; } @SuppressWarnings("checkstyle:MissingJavadocMethod") public static Map objList2Map(Class clazz, List list){ return objList2Map(clazz, list, "id"); } /** * 根据类类型和属性名称获取对应的Field对象 * @param clazz 类类型 * @param fieldName 属性名 * @param 类泛型 * @return 属性对象 */ public static Field getField(Class clazz, String fieldName){ try { return clazz.getDeclaredField(fieldName); } catch (NoSuchFieldException e) { throw new MyInnerException(e); } } /** * 深克隆对象 * @param orig 对象 * @return 深克隆之后的对象 */ public static Object clone(Object orig) { Object obj = null; try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bos); out.writeObject(orig); out.flush(); out.close(); ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream(bos.toByteArray())); obj = in.readObject(); } catch (Exception e) { throw new MyInnerException(e); } return obj; } /** * 将第一个对象的值复制到第二个对象中 * @param sourceObj 源实体 * @param targetObj 目标实体 * @param fields 需要复制的属性(可以为空,为空则默认复制全部,且受黑名单与白名单的约束) * @param notFields 黑名单 * @param yesFields 白名单 * @param 源泛型 * @param 目标泛型 */ public static void copyData(T1 sourceObj, T2 targetObj, Field[] fields, Field[] notFields, Field[] yesFields){ if(sourceObj == null || targetObj == null){ throw new MyInnerException("对象不能为null"); } if(fields != null && fields.length > 0){ //fields存在时,not和yes不生效,仅复制fields中的属性 for (Field field : fields) { copyFieldValue(sourceObj, targetObj, field); } } else if(notFields != null || yesFields != null) { //fields不存在则not和yes生效,循环所有字段并复制 fields = sourceObj.getClass().getDeclaredFields(); for(Field field : fields) { boolean notFlag = CollectionUtil.isExist(notFields, field, Field.class, "getName"); boolean yesFlag = CollectionUtil.isExist(yesFields, field, Field.class, "getName"); if(yesFlag || !notFlag){ copyFieldValue(sourceObj, targetObj, field); } } } else { Field[] fieldList = sourceObj.getClass().getDeclaredFields(); ReflectUtil.fieldAccess(true, fieldList); for (Field field : fieldList) { copyFieldValue(sourceObj, targetObj, field); } ReflectUtil.fieldAccess(true, fieldList); } } @SuppressWarnings("checkstyle:MissingJavadocMethod") public static T2 copyData(T1 sourceObj, Class targetClass, Field[] fields, Field[] notFields, Field[] yesFields){ T2 targetObj = EntityUtil.getInstance(targetClass); copyData(sourceObj, targetObj, fields, notFields, yesFields); return targetObj; } @SuppressWarnings("checkstyle:MissingJavadocMethod") public static void copyData(T1 sourceObj, T2 targetObj){ copyData(sourceObj, targetObj, null, null, null); } @SuppressWarnings("checkstyle:MissingJavadocMethod") public static T2 copyData(T1 sourceObj, Class targetClass){ T2 targetObj = EntityUtil.getInstance(targetClass); copyData(sourceObj, targetObj); return targetObj; } /** * 将列表对象转换为另一个列表对象 * @param sourceList 源实体 * @param sourceClass 目标实体 * @param fields 需要复制的属性(可以为空,为空则默认复制全部,且受黑名单与白名单的约束) * @param notFields 黑名单 * @param yesFields 白名单 * @param 源泛型 * @param 目标泛型 * @return 部门对象集合 */ public static List copyListData(Collection sourceList, Class sourceClass, Field[] fields, Field[] notFields, Field[] yesFields){ List list = new ArrayList<>(); for (T1 source : sourceList) { list.add(copyData(source, sourceClass, fields, notFields, yesFields)); } return list; } /** * 将第一个对象的指定属性复制到第二个对象中 * @param sourceObj 源实体 * @param targetObj 目标实体 * @param field 属性对象 * @param 源泛型 * @param 目标泛型 */ private static void copyFieldValue(T1 sourceObj, T2 targetObj, Field field) { T1 t1 = ReflectUtil.invokeGet(sourceObj, field); if(t1 != null) { ReflectUtil.invokeSet(targetObj, field, t1); } } /** * 复制字段的值????这特么是啥 * @param sourceObj 被转换的 * @param targetObj 转换得到的 - null * @param field1 源属性对象 * @param field2 目标属性对象 * @param 源泛型 * @param 目标泛型 */ public static void copyFieldValue(T1 sourceObj, T2 targetObj, Field field1, Field field2) { //1. 判断两个字段是否名称相同而且类型相同 if (field1.getName().equals(field2.getName()) && EntityUtil.equalFieldsType(field1, field2)) { //2. 获取源数据字段的值 field1.setAccessible(true); Object value = ReflectUtil.invokeGet(sourceObj, field1); //3. 给目标数据字段赋值 field2.setAccessible(true); ReflectUtil.invokeSet(targetObj, field2, value); //4. 访问权限还原 ReflectUtil.fieldAccess(false, field1, field2); return; } if (field1.getName().equals(field2.getName())){ String fTypeName1 = field1.getType().getSimpleName(); String fTypeName2 = field2.getType().getSimpleName(); String dateName = Date.class.getSimpleName(); String stringName = String.class.getSimpleName(); ReflectUtil.fieldAccess(true, field1, field2); Object value = ReflectUtil.invokeGet(sourceObj, field1); if(value == null) { return; } if(fTypeName1.equals(stringName) && fTypeName2.equals(dateName)){ field2.setAccessible(true); try { ReflectUtil.invokeSet(targetObj, field2, new SimpleDateFormat("yyyy-MM-dd").parse((String) value)); } catch (ParseException e) { throw new MyInnerException(e); } //4. 访问权限还原 ReflectUtil.fieldAccess(false, field1, field2); } if(fTypeName1.equals(dateName) && fTypeName2.equals(stringName)){ ReflectUtil.fieldAccess(true, field1, field2); //3. 获取源数据字段的值给目标数据字段赋值 ReflectUtil.invokeSet(targetObj, field2, new SimpleDateFormat("yyyy-MM-dd").format((Date) value)); //4. 访问权限还原 ReflectUtil.fieldAccess(false, field1, field2); } } } }

PS:

文章链接

《工具类篇1——POI工具类》——待更新
《工具类篇2——集合工具类》
《工具类篇3——反射工具类》(共三篇)
《工具类篇4——大数字工具类》(共三篇)——待更新
《工具类篇5——时间戳工具类》(共两篇)——待更新
《工具类篇6——字符串工具类》——待更新
《工具类篇7——线程池工具类》——待更新
《…》

你可能感兴趣的:(工具类,Java,java,反射,开发工具,工具类)