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

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

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

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


目录
相关文章
|
7月前
|
设计模式 Java
Java克隆方式避免频繁创建对象优化方案
Java克隆方式避免频繁创建对象优化方案
51 0
|
5月前
|
存储
【克隆方法+深浅拷贝】
【克隆方法+深浅拷贝】
35 0
|
11月前
|
存储 JSON JavaScript
Javascript中的对象拷贝(对象复制/克隆)
本文介绍 Javascript中的对象拷贝(对象复制/克隆)的实现方式
209 0
Javascript中的对象拷贝(对象复制/克隆)
六个方法两个拷贝带你透彻对象合并问题
实际场景下,我们经常需要进行对象合并的操作,而有时候原对象的改变会改变合并后的对象,这是一个非常严重的问题,涉及到了合并对象中的深浅拷贝,递归遍历,让人发蒙。
117 1
|
PHP 开发者
对象克隆|学习笔记
快速学习对象克隆
83 0
对象克隆|学习笔记
创建对象三步骤
创建对象三步骤
86 0
|
Java API
Java对象的深克隆与浅克隆(对象复制)(上)
Java对象的深克隆与浅克隆(对象复制)(上)
105 0
Java对象的深克隆与浅克隆(对象复制)(上)
|
Java 编译器
Java对象的深克隆与浅克隆(对象复制)(下)
Java对象的深克隆与浅克隆(对象复制)(下)
134 0
Java对象的深克隆与浅克隆(对象复制)(下)
|
Java 开发者
对象克隆|学习笔记
快速学习对象克隆
原型模式:克隆生成对象
原型模式的本质是克隆生成对象
945 0
原型模式:克隆生成对象