文档章节

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

白志华
 白志华
发布于 2015/10/18 10:55
字数 1157
阅读 8
收藏 0
点赞 0
评论 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

共有 人打赏支持
白志华
粉丝 29
博文 265
码字总数 57524
作品 0
长沙
程序员
Effective Java 第三版——13. 谨慎地重写 clone 方法

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

M104
01/04
0
0
Cloneable Interface in java

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

Rksi5
2014/04/24
0
0
Java Object对象之clone方法

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

viakiba
2016/11/28
11
0
Hutool之类处理相关工具——ClassUtil

类处理工具 这个工具主要是封装了一些反射的方法,使调用更加方便。而这个类中最有用的方法是方法,这个方法会扫描classpath下所有类,这个在Spring中是特性之一,主要为Hulu框架中类扫描的一...

路小磊
2014/05/23
0
0
设计模式学习笔记九:原型模式(Prototype Pattern)

1.概述 意图:我们将已经存在的对象作为原型,用户可以通过复制这些原型创建新的对象。 使用场合:当一个系统应该独立于产品的创建、构造和表示时,可以使用原型模式。在原型模式中,产品的...

长平狐
2013/06/17
60
0
Java设计模式百例(番外) - Java的clone

本文源码见:https://github.com/get-set/get-designpatterns/tree/master/prototype 本文是为下一篇“Java设计模式百例 - 原型模式”做铺垫,讨论一下Java中的对象克隆。本文内容综合了《E...

享学IT
2017/11/17
0
0
深入理解原型模式 ——通过复制生成实例

Java面试通关手册(Java学习指南,欢迎Star,会一直完善下去,欢迎建议和指导):https://github.com/Snailclimb/Java_Guide一 原型模式介绍 在面向对象系统中,使用原型模式来复制一个对象自...

Amsour丶
06/19
0
0
四、JAVA基础--接口与反射总结

一、接口 接口中所有的方法默认public static final,不必再写。 接口中可以定义常量,但不能含有实例域。在java SE8之前,不能在接口中实现方法。 一个类可以实现多个方法implements 接口1...

cnslp
2017/04/22
0
0
Java基础——面向对象(Object父类)

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。 Object 父类: Object的方法: clone() Object...

凯哥学堂
07/12
0
0
Java对象复制

1.Java对象复制概念 1.1 浅复制(浅克隆) 复制的对象的所有变量与含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引...

kukudeku
2016/09/30
40
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

什么是Base64

一、什么是Base64? 百度百科中对Base64有一个很好的解释:“Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法”。 什么是...

Jack088
6分钟前
0
0
SQL多表联查leftjoin左边加表单

SELECT IFNULL(u.USER_ACCOUNT, o.USER_ACCOUNT) u.USER_ACCOUNT, o.* FROM gh_orders o LEFT JOIN gh_user u ON o.PARENT_ID = u.ROW_ID 1.假如u.USER_ACCOUNT不空返回u.USER_ACCOUNT,否则返......

森火
10分钟前
0
0
expect脚本同步文件、expect脚本指定host和要同步的文件、构建文件分发系统

expect脚本同步文件 更改权限 执行脚本 查看执行结果 expect eof需要加上,作用是等脚本命令执行完再进行退出 expect脚本指定host和要同步的文件 更改权限,执行脚本 构建文件分发系统 需求背...

Zhouliang6
48分钟前
1
0
Hive应用:外部分区表

Hive应用:外部分区表 介绍 Hive可以创建外部分区表。创建表的时候,分区要在建表语句中体现。建完之后,你不会在表中看到数据,需要进行分区添加,使用alter语句进行添加。然后数据才会显示...

星汉
59分钟前
3
0
点击Enter登录

1. 效果 2. 实现过程(记得引入jq文件) //6.回车事件 登录 $(function() { document.onkeydown = function(event) { var e = event || window.event || arguments.callee.caller.arguments......

Lucky_Me
今天
1
0
点击菜单内容切换

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .menu{ height: 38px; background-color: #eeeeee; line-height: 38px; } .mao{ ......

南桥北木
今天
1
0
OSChina 周六乱弹 —— 妹子和游戏哪个更好玩

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @andonny :分享唐朝乐队的单曲《国际歌》 《国际歌》- 唐朝乐队 手机党少年们想听歌,请使劲儿戳(这里) @举个栗子- :日常祈雨 邪恶的大祭...

小小编辑
今天
613
8
流利阅读笔记32-20180721待学习

“人工智能”造假:只有人工,没有智能 Lala 2018-07-21 1.今日导读 当今社会,擅长单个方面的人工智能已经盛行,手机借助 AI 智慧防抖技术帮助大家拍出清晰照片,谷歌研发的 AI 助手将可以帮...

aibinxiao
今天
10
0
我的成长记录(一)

今天突然精神抖擞,在我的博客下新开一项分类>成长记录,专门记录每隔一段时间我的一点感悟吧。因为今天才专门花时间新开这样一个分类,所以以前有过的一些感悟没有记录下来,现在已经想不起...

dtqq
今天
1
0
机器学习管理平台 MLFlow

最近工作很忙,博客一直都没有更新。抽时间给大家介绍一下Databrick开源的机器学习管理平台-MLFlow。 谈起Databrick,相信即使是不熟悉机器学习和大数据的工程湿们也都有所了解,它由Spark的...

naughty
今天
19
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部