Merging two objects in Java

Viewed 84970

I have two objects of same type.

Class A {
  String a;
  List b;
  int c;
}

A obj1 = new A();
A obj2 = new A();

obj1 => {a = "hello"; b = null; c = 10}
obj2 => {a = null; b = new ArrayList(); c = default value}

Can you please let me know what is the best way to combine this objects into single object?

obj3 = {a = "hello"; b = (same arraylist from obj2); c = 10}
9 Answers

Add this method to your POJO, then use it like myObject.merge(newObject). It uses generics to loop through your POJO's fields, so you don't mention any field names:

/**
 * Fill current object fields with new object values, ignoring new NULLs. Old values are overwritten.
 *
 * @param newObject Same type object with new values.
 */
public void merge(Object newObject) {

  assert this.getClass().getName().equals(newObject.getClass().getName());

  for (Field field : this.getClass().getDeclaredFields()) {

    for (Field newField : newObject.getClass().getDeclaredFields()) {

      if (field.getName().equals(newField.getName())) {

        try {

          field.set(
              this,
              newField.get(newObject) == null
                  ? field.get(this)
                  : newField.get(newObject));

        } catch (IllegalAccessException ignore) {
          // Field update exception on final modifier and other cases.
        }
      }
    }
  }
}

There is a dynamic solution to merge any two objects which require Reflection and Recursion.

public <T> T merge(T local, T remote, ArrayList<String> listOfClass)
        throws IllegalAccessException, InstantiationException {
    Class<?> clazz = local.getClass();
    Object merged = clazz.newInstance();
    for (Field field : clazz.getDeclaredFields()) {
        field.setAccessible(true);
        Object localValue = field.get(local);
        Object remoteValue = field.get(remote);
        if (localValue != null) {
            if (listOfClass.contains(localValue.getClass().getSimpleName())) {
                field.set(merged, this.merge(localValue, remoteValue, listOfClass));
            } else {
                field.set(merged, (remoteValue != null) ? remoteValue : localValue);
            }
        } else if (remoteValue != null) {
            field.set(merged, remoteValue);
        }
    }
    return (T) merged;
}

Variable Description:

  • local: The object on to which the other will be merged
  • remote: The object which will be merged to the local object
  • listOfClass: The ArrayList of custom classes in the given object

The function returns a merged object which is good to go.

Kudos! :)

public static Object mergeObjects(Object source, Object target) throws Exception {
        Field[] allFields = source.getClass().getDeclaredFields();
        for (Field field : allFields) {
            if(Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers())){
                continue;
            }

            if (!field.isAccessible() && Modifier.isPrivate(field.getModifiers()))
                field.setAccessible(true);
            if (field.get(source) != null) {
                field.set(target, field.get(source));
            }
        }

        return target;
    }

Using java reflection, support only for the same class.

Related