在Java中合并两个对象



我有两个相同类型的对象。

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}

你能告诉我把这些物体组合成一个物体的最好方法是什么吗?

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

只要POJO有自己的getter和setter,这就可以工作。该方法使用update中的非null值更新obj。它在obj上调用setParameter((,在更新时返回getParameter(

public void merge(Object obj, Object update){
    if(!obj.getClass().isAssignableFrom(update.getClass())){
        return;
    }
    Method[] methods = obj.getClass().getMethods();
    for(Method fromMethod: methods){
        if(fromMethod.getDeclaringClass().equals(obj.getClass())
                && fromMethod.getName().startsWith("get")){
            String fromName = fromMethod.getName();
            String toName = fromName.replace("get", "set");
            try {
                Method toMetod = obj.getClass().getMethod(toName, fromMethod.getReturnType());
                Object value = fromMethod.invoke(update, (Object[])null);
                if(value != null){
                    toMetod.invoke(obj, value);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } 
        }
    }
}

我使用的是Spring Framework。我在一个项目上也遇到了同样的问题
为了解决这个问题,我使用了BeanUtils类和上面的方法

public static void copyProperties(Object source, Object target)

这是一个例子,

public class Model1 {
    private String propertyA;
    private String propertyB;
    public Model1() {
        this.propertyA = "";
        this.propertyB = "";
    }
    public String getPropertyA() {
        return this.propertyA;
    }
    public void setPropertyA(String propertyA) {
        this.propertyA = propertyA;
    }
    public String getPropertyB() {
        return this.propertyB;
    }
    public void setPropertyB(String propertyB) {
        this.propertyB = propertyB;
    }
}
public class Model2 {
    private String propertyA;
    public Model2() {
        this.propertyA = "";
    }
    public String getPropertyA() {
        return this.propertyA;
    }
    public void setPropertyA(String propertyA) {
        this.propertyA = propertyA;
    }
}
public class JustATest {
    public void makeATest() {
        // Initalize one model per class.
        Model1 model1 = new Model1();
        model1.setPropertyA("1a");
        model1.setPropertyB("1b");
        Model2 model2 = new Model2();
        model2.setPropertyA("2a");
        // Merge properties using BeanUtils class.
        BeanUtils.copyProperties(model2, model1);
        // The output.
        System.out.println("Model1.propertyA:" + model1.getPropertyA(); //=> 2a
        System.out.println("Model1.propertyB:" + model1.getPropertyB(); //=> 1b
    }
}

也许类似

class A {
    String a;
    List<..> b;
    int c;
    public void merge(A other) {
        this.a = other.a == null ? this.a : other.a;
        this.b.addAll(other.b);
        this.c = other.c == 0 ? this.c : other.c;
    }
}
A a1 = new A();
A a2 = new A();
a1.a = "a prop";
a2.c = 34;
a1.merge(a2);

CCD_ 1可能返回一个新的CCD_。

只适应布尔同步。和区分大小写(骆驼符号(

public boolean merge(Object obj){
    if(this.equals(obj)){
        return false;
    }
    if(!obj.getClass().isAssignableFrom(this.getClass())){
        return false;
    }
    Method[] methods = obj.getClass().getMethods();
    for(Method fromMethod: methods){
        if(fromMethod.getDeclaringClass().equals(obj.getClass())
                && (fromMethod.getName().matches("^get[A-Z].*$")||fromMethod.getName().matches("^is[A-Z].*$"))){
            String fromName = fromMethod.getName();
            String toName ;
            if(fromName.matches("^get[A-Z].*")){
                toName = fromName.replace("get", "set");
            }else{
                toName = fromName.replace("is", "set");
            }
            try {
                Method toMetod = obj.getClass().getMethod(toName, fromMethod.getReturnType());
                Object value = fromMethod.invoke(this, (Object[])null);
                if(value != null){
                    toMetod.invoke(obj, value);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } 
        }
    }
    return true;
}

如果为属性创建getter和setter,则可以使用Commons BeanUtils中的copyProperties方法。

将这个方法添加到POJO中,然后像myObject.merge(newObject)一样使用它。它使用泛型在POJO的字段中循环,因此您不提及任何字段名

/**
 * 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.
        }
      }
    }
  }
}

有一个动态解决方案可以合并任何两个需要反射和递归的对象。

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

变量描述:

  • local:另一个将合并到的对象
  • remote:将合并到本地对象的对象
  • listOfClass:给定对象中自定义类的ArrayList

该函数返回一个合并后的对象,这很好。

荣誉!:(

在非常特殊的情况下,您似乎想要一个新对象,该对象从两个实例中获取真实值。这里有一个实现可以做到这一点。应该将该方法添加到类A中,以便它可以访问字段。

 public A specialMergeWith(A other) {
   A result = new A();
   result.a = (a == null ? other.a : a);
   result.b = (b == null ? other.b : b);
   result.c = (c == DEFAULT_VALUE ? other.c : c);
   return result;
 }
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;
    }

使用java反射,只支持同一个类。

相关内容

  • 没有找到相关文章

最新更新