在Java中合并两个对象

tam*_*nad 11 java reflection

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

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}
Run Code Online (Sandbox Code Playgroud)

你能否告诉我将这些对象组合成单个对象的最佳方法是什么?

obj3 = {a = "hello"; b = (same arraylist from obj2); c = 10}
Run Code Online (Sandbox Code Playgroud)

Ale*_*nez 24

只要您拥有自己的getter和setter的POJO,这就有效.该方法使用update中的非null值更新obj.它在obj上调用setParameter(),并在update上调用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();
            } 
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • `String toName = fromName.replace("get", "set");` 如果我有一个名为 `thisisfieldsett` 的字段,会发生什么? (3认同)

Cro*_*zin 8

也许是这样的

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);
Run Code Online (Sandbox Code Playgroud)

A.merge可能会返回一个新A对象而不是修改当前对象.

  • NullPointerException,因为`this.b`可能是`null`,并且它没有满足`b`的"obj2的相同arraylist"请求 (3认同)

Geo*_*lou 8

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

public static void copyProperties(Object source, Object target)
Run Code Online (Sandbox Code Playgroud)

这是一个例子,

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
    }
}
Run Code Online (Sandbox Code Playgroud)

  • `BeanUtils.copyProperties` 不会检查复制的属性是否有 `null` 并忽略它们。 (3认同)

小智 7

只是容纳布尔同步.区分大小写(骆驼表示法)

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;
}
Run Code Online (Sandbox Code Playgroud)


Thi*_*rte 6

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


Zon*_*Zon 5

将此方法添加到您的 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.
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)