文档章节

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

白志华
 白志华
发布于 2015/10/18 10:55
字数 1157
阅读 9
收藏 0

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

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


版权声明:本文为博主原创文章,未经博主允许不得转载。

本文转载自:http://blog.csdn.net/xiaoxian8023/article/details/43312929

共有 人打赏支持
白志华
粉丝 31
博文 265
码字总数 57524
作品 0
长沙
程序员
私信 提问
【设计模式】原型模式 Pototype Parttern

前面讲了创建一个对象实例的方法单例模式Singleton Parttern, 创造多个产品的工厂模式(简单工厂模式 Simple Factory Pattern, 工厂方法模式 FactoryMothed Parttern,抽象工厂模式 Abstra...

风之源
08/06
0
0
Cloneable Interface in java

一个类实现该接口表明该类的实例通过java.lang.Object#clone()方法拷贝字段的字段是合法的。 在一个没有实现该接口的实例上调用对象的clone方法会抛出CloneNotSupportedException异常。 通常...

Rksi5
2014/04/24
0
0
Java拾遗:008 - 对象克隆与浅拷贝、深拷贝

对象克隆 Object类中有一个方法叫,完整代码 首先它是一个Native方法,而且是受保护的(),抛出一个异常(JDK1.8)。 通常程序员自己定义的类不能直接调用方法,如果要在外部调用,需要重写...

一别丶经年
08/04
0
0
Effective Java 第三版——13. 谨慎地重写 clone 方法

Tips 《Effective Java, Third Edition》一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8...

M104
01/04
0
0
Java Object对象之clone方法

克隆的步骤: 创建一个对象 将原有对象的数据导入到新创建的数据中 1. Object的clone()源代码简介 clone方法首先会判对象是否实现了Cloneable接口,若无则抛出CloneNotSupportedException, 最...

viakiba
2016/11/28
11
0

没有更多内容

加载失败,请刷新页面

加载更多

集群介绍 ..

12月19日任务 18.1 集群介绍 18.2 keepalived介绍 18.3/18.4/18.5 用keepalived配置高可用集群 一.集群介绍 根据功能划分为两大类:高可用和负载均衡 高可用集群通常为两台服务器,一台工作,...

hhpuppy
17分钟前
0
0
TensorFlow的基础概念02

TensorFlow的计算流图 import osos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'#TensorFlow的计算模型,数据流图'''TensorFlow = Tensor + FlowTensor 张量 数据结构:多维数组Flo...

怪咖先生forever
23分钟前
1
0
大数据技术的发展趋势

大数据领域已经涌现出了大量新的技术,它们成为大数据采集、存储、处理和呈现的有力武器。这些技术下一步将如何发展?它们之中哪些技术将广为流行?又会诞生哪些新的技术? 技术趋向多样化,...

董黎明
38分钟前
8
0
藏在正则表达式里的陷阱

前几天线上一个项目监控信息突然报告异常,上到机器上后查看相关资源的使用情况,发现 CPU 利用率将近 100%。通过 Java 自带的线程 Dump 工具,我们导出了出问题的堆栈信息。 我们可以看到所...

前端小攻略
40分钟前
3
0
关联更新,关联查询

关联更新 update A,B SET A.c1=B.c1,A.c2=B.c2 where A.id=B.id and ... update A inner join on A.id=B.id set A.c1=B.c1,A.c2=B.c2 where... 关联查询 交叉连接(cross join),内连接(inner ......

关元
44分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部