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

我有两个java对象,我想将它们合并到单个对象中。 问题是两个对象不包含普通原始类型属性(字段),它们包含复杂类型属性(如其他类型的对象和其他类型的对象列表)。

对象1:通过设置一些属性(字段)和返回

对象2:通过设置一些属性(字段)返回,或者它可以返回它所拥有但不被对象1返回的类型的新对象。

对象1和对象2都是相同类型的。

结果对象3 = obj1属性+如果类型与obj1相同,则更新obj 2中的属性+来自obj2的新更新对象

使用spring提供的org.springframework.beans.BeanUtils类很容易做到。 或者Apache Commons BeanUtils库 ,我相信Springs版本或者基于或者是相同的。

 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; } 

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

尝试使用class.getFields

  Field[] fields = YourClass.getFields(); for (Field field : fields) { // get value YourObject value = field.get(objectInstance); // check the values are different, then update field.set(objetInstance, value); }