java中不同java对象属性间的属性复制怎么实现

博客分类:
编程过程中,有些时候某些不同的类有相同的字段,可能会遇到同时给他们赋值的情况。简单的时候,可以写重复的代码,重复太多的时候,就不如给一个赋值完,直接复制给另一个对象。
上面这种情况在数据库的实体类中比较常见。
java对象之间属性值复制在许多开源框架中也有实现,在这里介绍自实现、Spring、apache commons-beanutils三种实现方式。
一.自己实现简单的对象属性复制CopyUtil01.java
package com.bijian.
import java.beans.BeanI
import java.beans.I
import java.beans.PropertyD
* 复制的对象必须同时拥有setter和getter方法,只有一个的时候会报异常,都没有的时候就不复制
public class CopyUtil01 {
public static void Copy(Object source, Object dest) throws Exception {
//获取属性
BeanInfo sourceBean = Introspector.getBeanInfo(source.getClass(), java.lang.Object.class);
PropertyDescriptor[] sourceProperty = sourceBean.getPropertyDescriptors();
BeanInfo destBean = Introspector.getBeanInfo(dest.getClass(), java.lang.Object.class);
PropertyDescriptor[] destProperty = destBean.getPropertyDescriptors();
for (int i = 0; i & sourceProperty. i++) {
for (int j = 0; j & destProperty. j++) {
if (sourceProperty[i].getName().equals(destProperty[j].getName())) {
//调用source的getter方法和dest的setter方法
destProperty[j].getWriteMethod().invoke(dest, sourceProperty[i].getReadMethod().invoke(source));
} catch (Exception e) {
throw new Exception("属性复制失败:" + e.getMessage());
CopyUtil02.java
package com.bijian.
import java.lang.reflect.F
import java.lang.reflect.M
import java.util.L
import java.util.M
import java.util.S
* 该方法接收两个参数,一个是复制的源对象——要复制的对象,一个是复制的目标对象——对象副本。
* 当然这个方法也可以在两个不同对象间使用,这时候只要目标对象和对象具有一个或多个相同类型及名称的属性,那么就会把源对象的属性值赋给目标对象的属性
public class CopyUtil02 {
public static &T& T getBean(T TargetBean, T SourceBean) throws Exception {
if (TargetBean == null)
Field[] tFields = TargetBean.getClass().getDeclaredFields();
Field[] sFields = SourceBean.getClass().getDeclaredFields();
for (Field field : tFields) {
String fieldName = field.getName();
if (fieldName.equals("serialVersionUID"))
if (field.getType() == Map.class)
if (field.getType() == Set.class)
if (field.getType() == List.class)
for (Field sField : sFields) {
if (!sField.getName().equals(fieldName)) {
Class type = field.getType();
String setName = getSetMethodName(fieldName);
Method tMethod = TargetBean.getClass().getMethod(setName, new Class[] { type });
String getName = getGetMethodName(fieldName);
Method sMethod = SourceBean.getClass().getMethod(getName, null);
Object setterValue = sMethod.invoke(SourceBean, null);
tMethod.invoke(TargetBean, new Object[] { setterValue });
} catch (Exception e) {
throw new Exception("设置参数信息发生异常", e);
return TargetB
private static String getGetMethodName(String fieldName) {
fieldName = replaceFirstCharToUpper(fieldName);
return "get" + fieldN
private static String getSetMethodName(String fieldName) {
fieldName = replaceFirstCharToUpper(fieldName);
return "set" + fieldN
private static String replaceFirstCharToUpper(String fieldName) {
char[] chars = new char[1];
chars[0] = fieldName.charAt(0);
String temp = new String(chars);
if (chars[0] &= 'a' && chars[0] &= 'z') {
fieldName = fieldName.replaceFirst(temp, temp.toUpperCase());
return fieldN
CopyUtil03.java
package com.bijian.
import java.lang.reflect.M
import java.util.A
import java.util.C
import java.util.L
* 采用反射,通过源对象getter 方法获取属性值,并通过目标对象的setter方法设置到目标对象中去
public class CopyUtil03 {
* 利用反射实现对象之间属性复制
* @param from
* @param to
public static void copyProperties(Object from, Object to) throws Exception {
copyPropertiesExclude(from, to, null);
* 复制对象属性
* @param from
* @param to
* @param excludsArray 排除属性列表
* @throws Exception
@SuppressWarnings("unchecked")
public static void copyPropertiesExclude(Object from, Object to, String[] excludsArray) throws Exception {
List&String& excludesList =
if(excludsArray != null && excludsArray.length & 0) {
excludesList = Arrays.asList(excludsArray); //构造列表对象
Method[] fromMethods = from.getClass().getDeclaredMethods();
Method[] toMethods = to.getClass().getDeclaredMethods();
Method fromMethod = null, toMethod =
String fromMethodName = null, toMethodName =
for (int i = 0; i & fromMethods. i++) {
fromMethod = fromMethods[i];
fromMethodName = fromMethod.getName();
if (!fromMethodName.contains("get"))
//排除列表检测
if(excludesList != null && excludesList.contains(fromMethodName.substring(3).toLowerCase())) {
toMethodName = "set" + fromMethodName.substring(3);
toMethod = findMethodByName(toMethods, toMethodName);
if (toMethod == null)
Object value = fromMethod.invoke(from, new Object[0]);
if(value == null)
//集合类判空处理
if(value instanceof Collection) {
Collection newValue = (Collection)
if(newValue.size() &= 0)
toMethod.invoke(to, new Object[] {value});
* 对象属性值复制,仅复制指定名称的属性值
* @param from
* @param to
* @param includsArray
* @throws Exception
@SuppressWarnings("unchecked")
public static void copyPropertiesInclude(Object from, Object to, String[] includsArray) throws Exception {
List&String& includesList =
if(includsArray != null && includsArray.length & 0) {
includesList = Arrays.asList(includsArray); //构造列表对象
Method[] fromMethods = from.getClass().getDeclaredMethods();
Method[] toMethods = to.getClass().getDeclaredMethods();
Method fromMethod = null, toMethod =
String fromMethodName = null, toMethodName =
for (int i = 0; i & fromMethods. i++) {
fromMethod = fromMethods[i];
fromMethodName = fromMethod.getName();
if (!fromMethodName.contains("get"))
//排除列表检测
String str = fromMethodName.substring(3);
if(!includesList.contains(str.substring(0,1).toLowerCase() + str.substring(1))) {
toMethodName = "set" + fromMethodName.substring(3);
toMethod = findMethodByName(toMethods, toMethodName);
if (toMethod == null)
Object value = fromMethod.invoke(from, new Object[0]);
if(value == null)
//集合类判空处理
if(value instanceof Collection) {
Collection newValue = (Collection)
if(newValue.size() &= 0)
toMethod.invoke(to, new Object[] {value});
* 从方法数组中获取指定名称的方法
* @param methods
* @param name
public static Method findMethodByName(Method[] methods, String name) {
for (int j = 0; j & methods. j++) {
if (methods[j].getName().equals(name))
return methods[j];
package com.bijian.
public class O1 {
private String aac001;
private String aac002;
private Double ddd001;
public String getAac001() {
return aac001;
public void setAac001(String aac001) {
this.aac001 = aac001;
public String getAac002() {
return aac002;
public void setAac002(String aac002) {
this.aac002 = aac002;
public Double getDdd001() {
return ddd001;
public void setDdd001(Double ddd001) {
this.ddd001 = ddd001;
package com.bijian.
public class O2 {
private String aac001;
private String aac002;
private Double ddd001;
private String aac003;
private String aac004;
public String getAac002() {
return aac002;
public void setAac002(String aac002) {
this.aac002 = aac002;
public String getAac001() {
return aac001;
public void setAac001(String aac001) {
this.aac001 = aac001;
public String getAac003() {
return aac003;
public void setAac003(String aac003) {
this.aac003 = aac003;
public String getAac004() {
return aac004;
public void setAac004(String aac004) {
this.aac004 = aac004;
public Double getDdd001() {
return ddd001;
public void setDdd001(Double ddd001) {
this.ddd001 = ddd001;
CopyJunitTest.java
package com.bijian.
import java.beans.I
import java.beans.PropertyD
import org.junit.A
import org.junit.B
import org.junit.T
public class CopyJunitTest {
public void setUp() {
this.o1 = new O1();
this.o2 = new O2();
this.o1.setAac001("00007");
this.o1.setAac002("国产零零零零七");
this.o1.setDdd001(Double.valueOf(3.793D));
public void test_copyUtil01() {
CopyUtil01.Copy(this.o1, this.o2);
System.out.println("CopyUtil01单元测试");
System.out.println("-------------源对象o1----------------");
showObjectPropertyValue(this.o1);
System.out.println("-------------目标对象o2----------------");
showObjectPropertyValue(this.o2);
System.out.println();
} catch (Exception e) {
Assert.fail();
public void test_copyUtil02() {
this.o2 = ((O2) CopyUtil02.getBean(this.o2, this.o1));
System.out.println("CopyUtil02单元测试");
System.out.println("-------------源对象o1----------------");
showObjectPropertyValue(this.o1);
System.out.println("-------------目标对象o2----------------");
showObjectPropertyValue(this.o2);
System.out.println();
} catch (Exception e) {
Assert.fail();
public void test_copyUtil03_copyProperties() {
CopyUtil03.copyProperties(this.o1, this.o2);
System.out.println("CopyUtil03的copyProperties方法单元测试");
System.out.println("-------------源对象o1----------------");
showObjectPropertyValue(this.o1);
System.out.println("-------------目标对象o2----------------");
showObjectPropertyValue(this.o2);
System.out.println();
} catch (Exception e) {
Assert.fail();
public void test_copyUtil03_copyPropertiesExclude() {
String[] excludsArray = new String[1];
excludsArray[0] = "aac001";
CopyUtil03.copyPropertiesExclude(this.o1, this.o2, excludsArray);
System.out.println("CopyUtil03的copyPropertiesExclude方法单元测试");
System.out.println("-------------源对象o1----------------");
showObjectPropertyValue(this.o1);
System.out.println("-------------目标对象o2----------------");
showObjectPropertyValue(this.o2);
System.out.println();
} catch (Exception e) {
Assert.fail();
public void test_copyUtil03_copyPropertiesInclude() {
String[] includsArray = new String[2];
includsArray[0] = "aac001";
includsArray[1] = "ddd001";
CopyUtil03.copyPropertiesInclude(this.o1, this.o2, includsArray);
System.out.println("CopyUtil03的copyPropertiesInclude方法单元测试");
System.out.println("-------------源对象o1----------------");
showObjectPropertyValue(this.o1);
System.out.println("-------------目标对象o2----------------");
showObjectPropertyValue(this.o2);
} catch (Exception e) {
Assert.fail();
private void showObjectPropertyValue(Object o) throws Exception {
for (PropertyDescriptor property : Introspector.getBeanInfo(
o.getClass(), Object.class).getPropertyDescriptors())
System.out.println(property.getReadMethod()
.invoke(o, new Object[0]));
单元测试输出结果:
CopyUtil01单元测试
-------------源对象o1----------------
国产零零零零七
-------------目标对象o2----------------
国产零零零零七
CopyUtil02单元测试
-------------源对象o1----------------
国产零零零零七
-------------目标对象o2----------------
国产零零零零七
CopyUtil03的copyProperties方法单元测试
-------------源对象o1----------------
国产零零零零七
-------------目标对象o2----------------
国产零零零零七
CopyUtil03的copyPropertiesExclude方法单元测试
-------------源对象o1----------------
国产零零零零七
-------------目标对象o2----------------
国产零零零零七
CopyUtil03的copyPropertiesInclude方法单元测试
-------------源对象o1----------------
国产零零零零七
-------------目标对象o2----------------
如上方式都是通过java的反射机制复制对象,不支持深度复制以及复制集合类型,但通用性会提高很多。java本身提供了对象复制的能力,在java.lang.Object类中有clone方法,该方法是一个protected方法,在子类需要重写此方法并声明为public类型,而且还需实现Cloneable接口才能提供对象复制的能力,clone()是一个native方法,native方法的效率一般来说都是远高于java中的非native方法,对性能比较关心的话应考虑这种方式。
二.利用Spring实现属性之间的复制
spring内部自有实现方法,如果我们需要在外面采用spring的托管复制,需要修改spring的源码,将spring中的org.springframework.beans.CachedIntrospectionResults类的forClass、getPropertyDescriptor、getBeanInfo改为可见的后重新打包。然后将Spring中关于复制的代码提取出来,最后修改成代码如下:
* 利用spring实现bean之间属性复制
* @param source
* @param target
@SuppressWarnings("unchecked")
public static void copyPropertiesBySpring(Object source, Object target) throws Exception {
Class actualEditable = target.getClass();
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
for (int i = 0; i & targetPds. i++) {
PropertyDescriptor targetPd = targetPds[i];
if (targetPd.getWriteMethod() != null) {
PropertyDescriptor sourcePd = getPropertyDescriptor(source
.getClass(), targetPd.getName());
if (sourcePd != null && sourcePd.getReadMethod() != null) {
Method readMethod = sourcePd.getReadMethod();
if (!Modifier.isPublic(readMethod.getDeclaringClass()
.getModifiers())) {
readMethod.setAccessible(true);
Object value = readMethod.invoke(source, new Object[0]);
if(value == null)
//集合类判空处理
if(value instanceof Collection) {
Collection newValue = (Collection)
if(newValue.size() &= 0)
Method writeMethod = targetPd.getWriteMethod();
if (!Modifier.isPublic(writeMethod.getDeclaringClass()
.getModifiers())) {
writeMethod.setAccessible(true);
writeMethod.invoke(target, new Object[] { value });
} catch (Throwable ex) {
* 获取指定类指定名称的属性描述符
* @param clazz
* @param propertyName
* @throws BeansException
@SuppressWarnings("unchecked")
public static PropertyDescriptor getPropertyDescriptor(Class clazz,
String propertyName) throws BeansException {
CachedIntrospectionResults cr = CachedIntrospectionResults.forClass(clazz);
return cr.getPropertyDescriptor(propertyName);
* 获取指定类得所有属性描述符
* @param clazz
* @throws BeansException
@SuppressWarnings("unchecked")
public static PropertyDescriptor[] getPropertyDescriptors(Class clazz) throws BeansException {
CachedIntrospectionResults cr = CachedIntrospectionResults.forClass(clazz);
return cr.getBeanInfo().getPropertyDescriptors();
三.利用apache commons-beanutils的开源实现
BeanUtils.copyProperties(dst, src)。方法能够将源对象和目标对象中相同名称的属性值复制过去。注意的是参数前面的是目标对象,后面是源对象。使用该方法需要注意:不能将入口方法与源对象、目标对象之一放在同一源文件之内,否者将没有任何效果。
PropertyUtils.copyProperties(dst, src)。功能与BeanUtils.copyProperties类似,只是在同属性名称的类型参数之间可以执行转换操作。
资料来源:
bijian1013
浏览: 1309038 次
来自: 深圳
看这里 这里这篇文章更详细 还有完整的实例演示:js跳出循环: ...
公钥能改成cer格式么
你的这个是没有服务端吗?
大牛 。膜拜
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'复制两个不同类型对象的相同字段的值
需求的来源是项目。
每次做项目,都要建立很多的数据体,有的是数据库表产生的ORM,有的是网络请求的参数体,有的是网络接口调用给的返回数据返回数据体。同一种数据,这几种数据具体的结构并不一样。
ORM往往跟数据表一致,并且做了映射。但是外键数据只有id,并不详细。
前端调用的数据往往要求比ORM更丰富,有些则不需要。虽说可以建立一些与ORM无关的字段来用,但是字段多了会很麻烦,所以需要建立专用的VO数据类。
接口请求的有些数据,比ORM的数据要少一些,并不需要前端传值,但是我们使用swagger做ApiDoc,不详细说明,前端也搞不清哪些必填,哪些可以不用,就连自己有时候也会搞乱,所以还是另外给前端建立一个request数据参数类比较合适。
但是这样一来,同一套数据就要在不同的数据对象之间读写不停,字段繁多的数据读写代码要写好多,看起来总觉得不舒服。
今天躺床上,一觉醒来,突然产生一种灵感:完全可以用反射来封装一个工具类,让程序自动判断匹配的字段,自动传值,不同的字段在做特殊处理,这样就会节省很多的代码。
说干就干,翻身起床,打开电脑,写一个demo。一会儿就写好了,调试通过。
一、建立一个实体类,模拟ORM插件生成那种,字段可以多一点。
@Entity(name = "tb_user")
public class UserEntity {
二、创建一个用于请求类,两个类之间的字段有交集
public class UserRequest {
}三、开始写工具类EntityUtils.java,有详细的注释
public class EntityUtils {
* 复制名称相同类型相同字段的值
* @param obj
* @param clazz2
* @param &T1&
* @param &T2&
public static &T1, T2& T2 copyData(T1 obj, Class&T2& clazz2) {
//1. 获取源数据的类
Class clazz1 = obj.getClass();//源数据类
//2. 创建一个目标数据实例
final T2 obj2 = getInstance(clazz2);
//3. 获取clazz1和clazz2中的属性
Field[] fields1 = clazz1.getDeclaredFields();
Field[] fields2 = clazz2.getDeclaredFields();
//4. 遍历fields2
for (Field f1 : fields1) {
//4-1. 遍历fields1,逐字段匹配
for (Field f2 : fields2) {
// 复制字段
copyField(obj, obj2, f1, f2);
return obj2;
* 按照字段表复制相同名称相同类型的字段的值
* @param obj
* @param clazz2
* @param fieldNames
* @param &T1&
* @param &T2&
public static &T1, T2& T2 copyData(T1 obj, Class&T2& clazz2, String[] fieldNames) {
//1. 获取源数据的类
Class clazz1 = obj.getClass();//源数据类
//2. 创建一个目标数据实例
final T2 obj2 = getInstance(clazz2);
//3. 获取clazz1和clazz2中的属性
Field[] fields1 = clazz1.getDeclaredFields();
Field[] fields2 = clazz2.getDeclaredFields();
//4. 遍历字段列表
for (String fieldName : fieldNames) {
//5. 遍历fields1
for (Field f1 : fields1) {
//找到这个字段(找不到就不用遍历fields2)
if (fieldName.equals(f1.getName())) {
//5-1. 遍历fields2,逐字段匹配
for (Field f2 : fields2) {
//在fields2中也要有这个字段
if (fieldName.equals(f2.getName())) {
//复制字段
copyField(obj, obj2, f1, f2);
return obj2;
* 复制相同名称相同类型的字段的值
* @param obj
* @param obj2
* @param f1
* @param f2
* @param &T1&
* @param &T2&
private static &T1, T2& void copyField(T1 obj, T2 obj2, Field f1, Field f2) {
//字段名要相同,字段类型也要相同
if (f1.getName().equals(f2.getName())
& f1.getType().getName().equals(f2.getType().getName())) {
System.out.println(f1.getName());
//3-2. 获取obj这个字段的值
f1.setAccessible(true);
Object val = f1.get(obj);
//3-3. 把这个值赋给obj2这个字段
f2.setAccessible(true);
f2.set(obj2, val);
//3-4. 访问权限还原
f2.setAccessible(false);
f1.setAccessible(false);
} catch (IllegalAccessException e) {
e.printStackTrace();
* 获得泛型类的实例
* @param tClass
* @param &T&
public static &T& T getInstance(Class&T& tClass) {
T t = tClass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
我喜欢使用的时候干干净净,所以习惯把异常在封装的时候解决掉,不喜欢抛出去。除非项目结构做了异常异常统一处理,需要throw.
四、写一个测试方法,来测试一下。
public void test() {
UserRequest userRequest = new UserRequest();
userRequest.setName("kalychen");
userRequest.setPassword("gk123456");
userRequest.setVcode("265847");
String[] fields = {"password"};
UserEntity userEntity = EntityUtils.copyData(userRequest, UserEntity.class, fields);
System.out.println(userEntity.getName());
System.out.println(userEntity.getPassword());
测试结果:
这测试的是带有字段列表的,可以看出没有在字段名称数组中出现的字段,即使是名称相同类型相同也不会复制。设计这样一个重载方法目的是方便控制。本来计划中还有一个使用注解来控制的重载,但是觉得未必会比前面两个更方便,所以放弃了。
今天是周末,感觉星期一我的项目代码又要删减好多了。繁琐的代码我看着会觉得很不舒服的。
补充一下,这些实体类都是没有继承的。
迭代了一下,对程序进行了优化和扩展
public class EntityUtils {
* 复制名称相同类型相同的字段数据
* @param sourceObj
* @param clazz
* @param &T1&
* @param &T2&
public static &T1, T2& T2 copyData(T1 sourceObj, Class&T2& clazz) {
//1. 获取源数据的类
Class&?& clazz1 = sourceObj.getClass();
//2. 创建一个目标数据对象
T2 targetObj = getInstance(clazz);
//3. 复制两个对象相同的字段
copyData(sourceObj, targetObj);
return targetO
* 根据字段列表复制字段的值
* @param sourceObj
* @param clazz
* @param fields
* @param &T1&
* @param &T2&
public static &T1, T2& T2 copyData(T1 sourceObj, Class&T2& clazz, String[] fields) {
//1. 获取源数据的类
Class&?& clazz1 = sourceObj.getClass();
//2. 创建一个目标数据对象
T2 targetObj = getInstance(clazz);
//3. 获取两个类字段集合
Field[] fields1 = clazz1.getDeclaredFields();
Field[] fields2 = clazz.getDeclaredFields();
//4. 复制字段
copyFieldValue(sourceObj, targetObj, fields, fields1, fields2);
return targetO
* 复制两个对象中相同字段的值
* @param sourceObj
* @param targetObj
* @param &T1&
* @param &T2&
public static &T1, T2& void copyData(T1 sourceObj, T2 targetObj) {
//1. 获取两个对象的类
Class&?& clazz1 = sourceObj.getClass();
Class&?& clazz2 = targetObj.getClass();
//3. 获取两个类字段集合
Field[] fields1 = clazz1.getDeclaredFields();
Field[] fields2 = clazz2.getDeclaredFields();
//4. 遍历fields1
for (Field f1 : fields1) {
//4-1. 遍历fields2
for (Field f2 : fields2) {
//4-2. 复制字段
copyFieldValue(sourceObj, targetObj, f1, f2);
* 根据字段表复制两个对象中相同字段的值
* @param sourceObj
* @param targetObj
* @param fields
* @param &T1&
* @param &T2&
public static &T1, T2& void copyData(T1 sourceObj, T2 targetObj, String[] fields) {
//1. 获取源两个对象的类
Class&?& clazz1 = sourceObj.getClass();
Class&?& clazz2 = targetObj.getClass();
//3. 获取两个类字段集合
Field[] fields1 = clazz1.getDeclaredFields();
Field[] fields2 = clazz2.getDeclaredFields();
//4. 复制字段
copyFieldValue(sourceObj, targetObj, fields, fields1, fields2);
* 根据字段列表排除复制对象中相同字段的值
* 凡是在字段列表中出现的不进行复制
* @param sourceObj
* @param clazz
* @param fields
* @param &T1&
* @param &T2&
public static &T1, T2& T2 copyDataExclude(T1 sourceObj, Class&T2& clazz, String[] fields) {
//1. 获取源数据的类
Class&?& clazz1 = sourceObj.getClass();
//2. 创建一个目标数据对象
T2 targetObj = getInstance(clazz);
//3. 获取两个类字段集合
Field[] fields1 = clazz1.getDeclaredFields();
Field[] fields2 = clazz.getDeclaredFields();
//4. 复制字段
copyFieldValueExclude(sourceObj, targetObj, fields, fields1, fields2);
return targetO
* 根据字段列表排除复制两个对象中相同字段的值
* 凡是在字段列表中出现的不进行复制
* @param sourceObj
* @param targetObj
* @param fields
* @param &T1&
* @param &T2&
public static &T1, T2& void copyDataExclude(T1 sourceObj, T2 targetObj, String[] fields) {
//1. 获取源两个对象的类
Class&?& clazz1 = sourceObj.getClass();
Class&?& clazz2 = targetObj.getClass();
//3. 获取两个类字段集合
Field[] fields1 = clazz1.getDeclaredFields();
Field[] fields2 = clazz2.getDeclaredFields();
//4. 复制字段
copyFieldValueExclude(sourceObj, targetObj, fields, fields1, fields2);
* 排除字段复制
* @param sourceObj
* @param targetObj
* @param fields
* @param fields1
* @param fields2
* @param &T1&
* @param &T2&
private static &T1, T2& void copyFieldValueExclude(T1 sourceObj, T2 targetObj, String[] fields, Field[] fields1, Field[] fields2) {
for (String fieldName : fields) {
//4-1. 遍历fields1
for (Field f1 : fields1) {
//4-3. 是否匹配这个字段
if (fieldName.equals(f1.getName())) {
//只要包含该字段就跳过
//4-4. 遍历fields2
for (Field f2 : fields2) {
//4-5. 复制字段
copyFieldValue(sourceObj, targetObj, f1, f2);
* 根据字段列表复制两个对象中相同字段的值
* @param sourceObj
* @param targetObj
* @param fields
* @param fields1
* @param fields2
* @param &T1&
* @param &T2&
private static &T1, T2& void copyFieldValue(T1 sourceObj, T2 targetObj, String[] fields, Field[] fields1, Field[] fields2) {
for (String fieldName : fields) {
//4-1. 遍历fields1
for (Field f1 : fields1) {
//4-3. 是否匹配这个字段
if (fieldName.equals(f1.getName())) {
//4-4. 遍历fields2
for (Field f2 : fields2) {
//4-3. 是否匹配这个字段
if (fieldName.equals(f2.getName())) {
//4-2. 复制字段
copyFieldValue(sourceObj, targetObj, f1, f2);
* 复制字段的值
* @param sourceObj
* @param targetObj
* @param field1
* @param field2
* @param &T1&
* @param &T2&
public static &T1, T2& void copyFieldValue(T1 sourceObj, T2 targetObj, Field field1, Field field2) {
//1. 判断两个字段是否名称相同而且类型相同
if (field1.getName().equals(field2.getName())
&& equalFieldsType(field1, field2)) {
//2. 获取源数据字段的值
field1.setAccessible(true);
Object value = field1.get(sourceObj);
//3. 给目标数据字段赋值
field2.setAccessible(true);
field2.set(targetObj, value);
//4. 访问权限还原
field2.setAccessible(false);
field1.setAccessible(false);
} catch (IllegalAccessException e) {
e.printStackTrace();
* 获取一个泛型的实例
* @param clazz
* @param &T&
public static &T& T getInstance(Class&T& clazz) {
return clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
* 判断两个字段的类型是否相同
* @param field1 复制源
* @param field2 复制目标
public static boolean equalFieldsType(Field field1, Field field2) {
String fTypeName1 = field1.getType().getSimpleName();
String fTypeName2 = field2.getType().getSimpleName();
System.out.println(fTypeName1 + ":" + fTypeName2);
//1. 处理基本数据类型和包装类
Map&String, String& map = new HashMap&String, String&();
map.put(int.class.getSimpleName(), Integer.class.getSimpleName());
map.put(byte.class.getSimpleName(), Byte.class.getSimpleName());
map.put(short.class.getSimpleName(), Short.class.getSimpleName());
map.put(char.class.getSimpleName(), Character.class.getSimpleName());
map.put(long.class.getSimpleName(), Long.class.getSimpleName());
map.put(float.class.getSimpleName(), Float.class.getSimpleName());
map.put(double.class.getSimpleName(), Double.class.getSimpleName());
map.put(boolean.class.getSimpleName(), Boolean.class.getSimpleName());
* 在涉及包装类的判断逻辑中,源数据不能是包装类
* 因为包装类一旦为null,会引发异常
Set&String& keySet = map.keySet();
for (String key : keySet) {
if (key.equals(fTypeName1) && map.get(key).equals(fTypeName2)) {
//2. 名称相同、类型相同
if (fTypeName1.equals(fTypeName2)) {
}看看这个工具类的作用效果吧!!
我们做alipay的异步通知接口,要把异步通知结果发送到我们的消息中心,然后推送到手机端。alipay服务器发送的参数大约有28个,我们在支付处理服务建立了一个带有gson字段映射的类,很好地解析了接收的字段信息。转身,我们要将这个对象作为参数发送到消息中心。那么问题来了。我们用retrofit2调用消息中心的接口,gs使用gson将数据打包,类的字段又会根据字段映射解析为原来的样子。而消息中心接收数据是不去理会字段映射的。我们把建好的类复制到消息中心去接收,就会出现很多字段收不到的情况。我们总不能再去建一个类吧?或者改变原来的类?总之很麻烦,令人很不爽。没办法我们就只能一个字段一个字段去转移了。
不过,一旦用上这个工具类,原来的二三十行代码就可以直接缩减为一行了。我们把原来的类复制一个,去掉所有的字段映射。
看看效果:
AlipayNoticeVO alipayNoticeVO = EntityUtils.copyData(alipayNotice,AlipayNoticeVO.class);
alipayNoticeVO.setAppId(alipayNotice.getAppId());
alipayNoticeVO.setBody(alipayNotice.getBody());
alipayNoticeVO.setBuyerId(alipayNotice.getBuyerId());
alipayNoticeVO.setBuyerLogonId(alipayNotice.getBuyerLogonId());
alipayNoticeVO.setBuyerPayAmount(alipayNotice.getBuyerPayAmount());
alipayNoticeVO.setGmtClose(alipayNotice.getGmtClose());
alipayNoticeVO.setGmtCreate(alipayNotice.getGmtCreate());
alipayNoticeVO.setGmtPayment(alipayNotice.getGmtPayment());
alipayNoticeVO.setGmtRefund(alipayNotice.getGmtRefund());
alipayNoticeVO.setInvoiceAmount(alipayNotice.getInvoiceAmount());
alipayNoticeVO.setNotifyId(alipayNotice.getNotifyId());
alipayNoticeVO.setNotifyTime(alipayNotice.getNotifyTime());
alipayNoticeVO.setNotifyType(alipayNotice.getNotifyType());
alipayNoticeVO.setOutBizNo(alipayNotice.getOutBizNo());
alipayNoticeVO.setOutTradeNo(alipayNotice.getOutTradeNo());
alipayNoticeVO.setPointAmount(alipayNotice.getPointAmount());
alipayNoticeVO.setReceiptAmount(alipayNotice.getReceiptAmount());
alipayNoticeVO.setSellerEmail(alipayNotice.getSellerEmail());
alipayNoticeVO.setSendBackFee(alipayNotice.getSendBackFee());
alipayNoticeVO.setSellerId(alipayNotice.getSellerId());
alipayNoticeVO.setSign(alipayNotice.getSign());
alipayNoticeVO.setSignType(alipayNotice.getSignType());
alipayNoticeVO.setSubject(alipayNotice.getSubject());
alipayNoticeVO.setTotalAmount(alipayNotice.getTotalAmount());
alipayNoticeVO.setTradeStatus(alipayNotice.getTradeStatus());
alipayNoticeVO.setTradeNo(alipayNotice.getTradeNo());
alipayNoticeVO.setFundBillList(alipayNotice.getFundBillList());
return alipayNoticeVO;
注释掉的是原来的代码。被第一行取代。
Java对象间属性值的复制-Spring的BeanUtil
BeanUtils的使用-在具有很多相同属性的两个bean之间复制属性值
Java中复制两个不同类的对象的属性
【项目从0到1】Java 快速复制两个类中的相同属性(无需继承关系)
两个具有相同属性的对象之间属性的拷贝
Java任意同类型对象的复制
java小算法介绍-合并List中满足某些字段相同的记录
复制两个不同类的对象的属性
Java比较两个对象是否相同并获得不同的字段
java 反射比较两个类型相同的对象 内部的变量是否相等
没有更多推荐了,}

我要回帖

更多关于 java对象属性 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信