博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
通过反射克隆对象,对象复制(克隆),对象合并工具类 升级版
阅读量:6273 次
发布时间:2019-06-22

本文共 4849 字,大约阅读时间需要 16 分钟。

       上一篇博文提到的工具类,主要是用在对象的复制方面,而且代码有点冗余了。这个工具类也是我现在在做的项目中用到的。

       现在在项目中遇到了一个 对象合并的需求。原先的工具类是不满足的,只能全部复制,所以又将原先的工具类做了修改。添加了对象合并的功能,同时还多设置了两个个参数,用一个boolean类型的参数来设定目标对象属性不为null时是否覆盖,用一个set来设定例外的情况。

package com.kaiyuan.common.util;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.HashMap;import java.util.Map;import java.util.Set;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * 通用对象copy工具类 *  * @author arron * @date 2015年1月9日 上午10:50:32 * @version 1.0 */public class ObjectCopyUtil {    private static final Logger logger = LoggerFactory.getLogger(ObjectCopyUtil.class);    		/**	 * 拷贝对象方法(适合同一类型的对象复制,但结果需强制转换)	 * 	 * @throws IllegalAccessException 	 * @throws InstantiationException 	 */	public static Object copy(Object objSource) throws InstantiationException, IllegalAccessException{        return copy(objSource,objSource.getClass());	}		/**	 * 拷贝对象方法(适合同一类型的对象复制)	 * 	 * @param objSource 源对象	 * @param clazz 目标类	 * @return	 * @throws InstantiationException	 * @throws IllegalAccessException	 */	public static 
T copy(Object objSource,Class
clazz) throws InstantiationException, IllegalAccessException{ if(null == objSource) return null;//如果源对象为空,则直接返回null T objDes = clazz.newInstance(); // 获得源对象所有属性 Field[] fields = clazz.getDeclaredFields(); // 循环遍历字段,获取字段对应的属性值 for ( Field field : fields ) { // 如果不为空,设置可见性,然后返回 field.setAccessible( true ); try { field.set(objDes, field.get(objSource)); } catch ( Exception e ) { logger.error("执行{}类的{}属性的set方法时出错。{}",clazz.getSimpleName(),field.getName(),e); } } return objDes; } /** * 拷贝对象方法(适合不同类型的转换)
* 前提是,源类中的所有属性在目标类中都存在 * * @param objSource 源对象 * @param clazzSrc 源对象所属class * @param clazzDes 目标class * @return * @throws InstantiationException * @throws IllegalAccessException */ public static
T copy(K objSource,Class
clazzSrc,Class
clazzDes ) throws InstantiationException, IllegalAccessException{ if(null == objSource) return null;//如果源对象为空,则直接返回null T objDes = clazzDes.newInstance(); return merge(objSource, objDes, clazzSrc, clazzDes); } /** * 合并对象方法(适合不同类型的转换)
* 前提是,源类中的所有属性在目标类中都存在 * * @param objSource 源对象 * @param clazzSrc 源对象所属class * @param clazzDes 目标class * @return * @throws InstantiationException * @throws IllegalAccessException */ public static
T merge(K objSource,T objDes,Class
clazzSrc,Class
clazzDes) throws InstantiationException, IllegalAccessException{ return merge(objSource, objDes, clazzSrc,clazzDes, true); } /** * 合并对象方法(适合不同类型的转换)
* 前提是,源类中的所有属性在目标类中都存在 * * @param objSource 源对象 * @param clazzSrc 源对象所属class * @param clazzDes 目标class * @param overwrite 是否覆盖已存在的属性值 * @return * @throws InstantiationException * @throws IllegalAccessException */ public static
T merge(K objSource,T objDes,Class
clazzSrc,Class
clazzDes,boolean overwrite) throws InstantiationException, IllegalAccessException{ return merge(objSource, objDes, clazzSrc,clazzDes, overwrite,null); } /** * 合并对象方法(适合不同类型的转换)
* 前提是,源类中的所有属性在目标类中都存在 * * @param objSource 源对象 * @param objDes 目标对象 * @param clazzSrc 源对象所属class * @param clazzDes 目标class * @param overwrite 是否覆盖已存在的属性值 * @param IgnoreMap 忽略的属性值 * @return * @throws InstantiationException * @throws IllegalAccessException */ public static
T merge(K objSource,T objDes,Class
clazzSrc,Class
clazzDes,boolean overwrite,Set
IgnoreSet) throws InstantiationException, IllegalAccessException{ if(null == objSource) return null;//如果源对象为空,则直接返回null //获取目标对象的所有属性 Field[] fieldDeses = clazzDes.getDeclaredFields(); Map
m = new HashMap
(); // 循环遍历字段,获取字段对应的属性值 for ( Field field : fieldDeses ) { // 如果不为空,设置可见性,然后返回 field.setAccessible( true ); m.put(field.getName(), field); } // 获得源对象所有属性 Field[] fields = clazzSrc.getDeclaredFields(); // 循环遍历字段,获取字段对应的属性值 for ( Field field : fields ) { //如果目标对象不存在该字段,则跳过 if(!m.containsKey(field.getName())) continue; // 如果不为空,设置可见性,然后返回 field.setAccessible( true ); try { String fieldName = field.getName();// 属性名 String firstLetter = fieldName.substring(0, 1).toUpperCase();// 获取属性首字母 // 拼接set方法名 String setMethodName = "set" + firstLetter + fieldName.substring(1); // 获取set方法对象 Method setMethod = clazzDes.getMethod(setMethodName,new Class[]{field.getType()}); //如果目标对象当前属性不为空 if(null!=m.get(fieldName).get(objDes)){ if(overwrite){//如果覆盖当前属性值,但map中存在,则不覆盖,否则覆盖 if(null!=IgnoreSet && IgnoreSet.contains(fieldName.toUpperCase())){//如果map中有值 continue; } }else{//如果不覆盖,但是map存在,则必须覆盖,否则不覆盖 if(null==IgnoreSet || !IgnoreSet.contains(fieldName.toUpperCase())){//如果map中没有值 continue; } } } // 对目标对象调用set方法装入属性值 setMethod.invoke(objDes, field.get(objSource)); } catch ( Exception e ) { logger.error("执行{}类的{}属性的set方法时出错。{}",clazzDes.getSimpleName(),field.getName(),e); } } return objDes; } }

转载地址:http://hmvpa.baihongyu.com/

你可能感兴趣的文章
微软发布Azure Stack硬件需求
查看>>
python socket编程详细介绍
查看>>
Windows Server 2016第三个技术预览版新技术
查看>>
Everything 本地磁盘文件搜索工具下载!
查看>>
Python dict(字典) 详细总结
查看>>
RPF(Reverse Path Forwarding 反向路径转发)技术
查看>>
2016年收到的第一件礼物,被评上微软全球最有价值专家MVP(一)
查看>>
2016中国VR开发者论坛第一期
查看>>
Hyper-V 2016 系列教程5 Hyper-V 服务器基本属性
查看>>
北京、天津工厂自动监测数据爬取
查看>>
第一个python程序简单加法计算器
查看>>
在CentOS下安装Tomcat8
查看>>
Weblogic classloader分析
查看>>
做技术做软件-----如何才能拿到上万的月薪
查看>>
linux 查看当前路径命令:pwd
查看>>
At.js – 用于 Web 应用程序的自动完成库
查看>>
[Android Pro] Android权限设置android.permission完整列表
查看>>
如何对抗硬件断点--- 调试寄存器
查看>>
mybatis学习
查看>>
从不同层面看cocos2d-x
查看>>