您的位置:首页 > 其它

通过反射克隆对象,对象复制(克隆),对象合并工具类 升级版

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

现在在项目中遇到了一个 对象合并的需求。原先的工具类是不满足的,只能全部复制,所以又将原先的工具类做了修改。添加了对象合并的功能,同时还多设置了两个个参数,用一个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;
}

}


版权声明:本文为博主原创文章,未经博主允许不得转载。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: