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

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

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

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

浅谈C++中对象的复制与对象之间的相互赋值_C 语言

C++对象的复制 有时需要用到多个完全相同的对象,例如,同一型号的每一个产品从外表到内部属性都是一样的,如果要对每一个产品分别进行处理,就需要建立多个同样的对象,并要进行相同的初始化,用以前的办法定义对象(同时初始化)比较麻烦.此外,有时需要将对象在某一瞬时的状态保留下来. C++提供了克隆对象的方法,来实现上述功能.这就是对象的复制机制. 用一个已有的对象快速地复制出多个完全相同的对象.如 Box box2(box1); 其作用是用已有的对象box1去克隆出一个新对象box2. 其一般形式为:

PHP动态地创建属性和方法, 对象的复制, 对象的比较,加载指定的文件,自动加载类文件,命名空间_php实例

PHP前言: •动态地创建属性和方法 •对象的复制 •对象的比较 •加载指定的文件 •自动加载类文件 •命名空间 示例 1.类的相关知识点 3(动态地创建属性和方法) class/class3.php <?php /** * 类的相关知识点 3(动态地创建属性和方法) */ // 用于演示如何动态地创建属性(这就是 php 中所谓的重载) class Class1 { // __set 魔术方法,当设置的属性不存在或者不可访问(private)时就会调用此函数 public function _

通过反射克隆对象,对象复制(克隆)工具类

       最近做的项目中,经常会遇到用视图来操作数据库的,但是页面需要的则是某个实体对象,在controller层查出list<view> 还要把将view对象转化成entity对象.需要写一大堆的get和set方法,而且如果实体增删字段的话,还需要把转化代码再修改一下,让人头疼.        当我需要操作一个实体对象完成两件不同的事情,这2个方法中会修改实体对象中的属性,第一个方法调用后,再调用第二个方法时,会受影响.为了保证不受影响,必须copy一份属性值一模一样的实体.这时候就需要

一行代码实现纯数据json对象的深度克隆实现思路_javascript技巧

复制代码 代码如下: var dataObjCloned=JSON.parse(JSON.stringify( dataObj )) 这是昨天晚上从大城小胖的微博上看到的,当时很感兴趣,就mark了下. 今天整理了下资料,分析下为什么一句话可以实现纯数据json对象的深度克隆. 1.JSON.stringify函数 复制代码 代码如下: 将 JavaScript 值转换为 JavaScript 对象表示法 (Json) 字符串. JSON.stringify(value [, replacer]

JavaScript对象之深度克隆介绍_javascript技巧

也不知道从什么时候开始,前端圈冒出了个新词:对象深度克隆.看起来好像很高大上的样子,实际上并不新鲜,在我们的实际项目开发中,你可能早已用到,只不过由于汉字的博大精深,有些原本很简单的事物被一些看似专业的词汇稍加修饰,就变得神秘起来了. 首先为什么要将一个对象进行深克隆?请允许我进行一个猜测:你有时一定会认为js的内置对象document太长,那么你可能会这样做: 复制代码 代码如下: var d = document; d.by = function(id){     return d.getE

说说对象的复制

以下为引用的内容:<%Dim oConn,oRsSet oConn = Server.CreateObject("ADODB.Connection")Set ors = Server.CreateObject("ADODB.RecordSet")oConn.open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("db1.mdb")Ses

复制js对象方法

复制js对象方法,需要的朋友可以参考下   复制代码 代码如下: CSSCommonJS.DeepCopy = function (json) {     if (typeof json == 'number' || typeof json == 'string' || typeof json == 'boolean') {         return json;     } else if (typeof json == 'object') {         if (json instan

JS将所有对象s的属性复制给对象r

 这篇文章主要介绍了js中将所有对象s的属性复制给对象r的方法,原生js+jquery分别实现 原生写法: 代码如下: /**    * 将所有 s 的属性复制给 r    * @param r {Object}    * @param s {Object}    * @param is_overwrite {Boolean} 如指定为 false ,则不覆盖已有的值,其它值    *   包括 undefined ,都表示 s 中的同名属性将覆盖 r 中的值    */   mix: func

超简易复制Model对象(为后续备忘录设计模式博文做铺垫)

超简易复制Model对象(为后续备忘录设计模式博文做铺垫) 复制整个Model需要实现NSCopy协议,可以想象是非常麻烦的一件事情,今天我跟大家分享一个不需要你做任何操作的复制Model对象的方法,不过,首先你得先去下载开源代码FastCoder辅助才行. 源码如下: NSObject+ObjectCopy.h 与 NSObject+ObjectCopy.m // // NSObject+ObjectCopy.h // FastCoder // // Created by YouXianMin