java 合并对象_如何在java中合并两个复杂对象

使用spring提供的org.springframework.beans.BeanUtils类很容易做到.或者我相信

Spring版本的

Apache Commons BeanUtils library要么基于或者是相同的.

public static T combine2Objects(T a, T b) throws InstantiationException, IllegalAccessException {

// would require a noargs constructor for the class, maybe you have a different way to create the result.

T result = (T) a.getClass().newInstance();

BeanUtils.copyProperties(a, result);

BeanUtils.copyProperties(b, result);

return result;

}

如果你不能或没有noargs构造函数,也许你只是传递结果

public static T combine2Objects(T a, T b, T destination) {

BeanUtils.copyProperties(a, destination);

BeanUtils.copyProperties(b, destination);

return destination;

}

如果你不想复制null属性,你可以使用这样的东西:

public static void nullAwareBeanCopy(Object dest, Object source) throws IllegalAccessException, InvocationTargetException {

new BeanUtilsBean() {

@Override

public void copyProperty(Object dest, String name, Object value)

throws IllegalAccessException, InvocationTargetException {

if(value != null) {

super.copyProperty(dest, name, value);

}

}

}.copyProperties(dest, source);

}

嵌套对象解决方案

这是一个更强大的解决方案.它支持嵌套对象复制,不再通过引用复制1级深的对象,而是克隆嵌套对象或单独复制其属性.

/**

* Copies all properties from sources to destination, does not copy null values and any nested objects will attempted to be

* either cloned or copied into the existing object. This is recursive. Should not cause any infinite recursion.

* @param dest object to copy props into (will mutate)

* @param sources

* @param dest

* @return

* @throws IllegalAccessException

* @throws InvocationTargetException

*/

public static T copyProperties(T dest, Object... sources) throws IllegalAccessException, InvocationTargetException {

// to keep from any chance infinite recursion lets limit each object to 1 instance at a time in the stack

final List lookingAt = new ArrayList<>();

BeanUtilsBean recursiveBeanUtils = new BeanUtilsBean() {

/**

* Check if the class name is an internal one

* @param name

* @return

*/

private boolean isInternal(String name) {

return name.startsWith("java.") || name.startsWith("javax.")

|| name.startsWith("com.sun.") || name.startsWith("javax.")

|| name.startsWith("oracle.");

}

/**

* Override to ensure that we dont end up in infinite recursion

* @param dest

* @param orig

* @throws IllegalAccessException

* @throws InvocationTargetException

*/

@Override

public void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException {

try {

// if we have an object in our list, that means we hit some sort of recursion, stop here.

if(lookingAt.stream().anyMatch(o->o == dest)) {

return; // recursion detected

}

lookingAt.add(dest);

super.copyProperties(dest, orig);

} finally {

lookingAt.remove(dest);

}

}

@Override

public void copyProperty(Object dest, String name, Object value)

throws IllegalAccessException, InvocationTargetException {

// dont copy over null values

if (value != null) {

// attempt to check if the value is a pojo we can clone using nested calls

if(!value.getClass().isPrimitive() && !value.getClass().isSynthetic() && !isInternal(value.getClass().getName())) {

try {

Object prop = super.getPropertyUtils().getProperty(dest, name);

// get current value, if its null then clone the value and set that to the value

if(prop == null) {

super.setProperty(dest, name, super.cloneBean(value));

} else {

// get the destination value and then recursively call

copyProperties(prop, value);

}

} catch (NoSuchMethodException e) {

return;

} catch (InstantiationException e) {

throw new RuntimeException("Nested property could not be cloned.", e);

}

} else {

super.copyProperty(dest, name, value);

}

}

}

};

for(Object source : sources) {

recursiveBeanUtils.copyProperties(dest, source);

}

return dest;

}

它有点快速和肮脏,但运作良好.因为它确实使用了递归,并且潜力无限递归,所以我确实放在了一个安全的位置.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值