上一篇博文提到的工具类,主要是用在对象的复制方面,而且代码有点冗余了。这个工具类也是我现在在做的项目中用到的。
现在在项目中遇到了一个 对象合并的需求。原先的工具类是不满足的,只能全部复制,所以又将原先的工具类做了修改。添加了对象合并的功能,同时还多设置了两个个参数,用一个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> T copy(Object objSource,Class<T> 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; } /** * 拷贝对象方法(适合不同类型的转换)<br/> * 前提是,源类中的所有属性在目标类中都存在 * * @param objSource 源对象 * @param clazzSrc 源对象所属class * @param clazzDes 目标class * @return * @throws InstantiationException * @throws IllegalAccessException */ public static <T, K> T copy(K objSource,Class<K> clazzSrc,Class<T> clazzDes ) throws InstantiationException, IllegalAccessException{ if(null == objSource) return null;//如果源对象为空,则直接返回null T objDes = clazzDes.newInstance(); return merge(objSource, objDes, clazzSrc, clazzDes); } /** * 合并对象方法(适合不同类型的转换)<br/> * 前提是,源类中的所有属性在目标类中都存在 * * @param objSource 源对象 * @param clazzSrc 源对象所属class * @param clazzDes 目标class * @return * @throws InstantiationException * @throws IllegalAccessException */ public static <T, K> T merge(K objSource,T objDes,Class<K> clazzSrc,Class<T> clazzDes) throws InstantiationException, IllegalAccessException{ return merge(objSource, objDes, clazzSrc,clazzDes, true); } /** * 合并对象方法(适合不同类型的转换)<br/> * 前提是,源类中的所有属性在目标类中都存在 * * @param objSource 源对象 * @param clazzSrc 源对象所属class * @param clazzDes 目标class * @param overwrite 是否覆盖已存在的属性值 * @return * @throws InstantiationException * @throws IllegalAccessException */ public static <T, K> T merge(K objSource,T objDes,Class<K> clazzSrc,Class<T> clazzDes,boolean overwrite) throws InstantiationException, IllegalAccessException{ return merge(objSource, objDes, clazzSrc,clazzDes, overwrite,null); } /** * 合并对象方法(适合不同类型的转换)<br/> * 前提是,源类中的所有属性在目标类中都存在 * * @param objSource 源对象 * @param objDes 目标对象 * @param clazzSrc 源对象所属class * @param clazzDes 目标class * @param overwrite 是否覆盖已存在的属性值 * @param IgnoreMap 忽略的属性值 * @return * @throws InstantiationException * @throws IllegalAccessException */ public static <T, K> T merge(K objSource,T objDes,Class<K> clazzSrc,Class<T> clazzDes,boolean overwrite,Set<String> IgnoreSet) throws InstantiationException, IllegalAccessException{ if(null == objSource) return null;//如果源对象为空,则直接返回null //获取目标对象的所有属性 Field[] fieldDeses = clazzDes.getDeclaredFields(); Map<String,Field> m = new HashMap<String, Field>(); // 循环遍历字段,获取字段对应的属性值 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; } }
时间: 2024-11-06 09:54:38