Merging two objects in Java

前端 未结 8 773
离开以前
离开以前 2020-12-15 23:25

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         


        
相关标签:
8条回答
  • 2020-12-15 23:53

    I am using Spring Framework. I was facing the same issue on a project.
    To solve it i used the class BeanUtils and the above method,

    public static void copyProperties(Object source, Object target)
    

    This is an example,

    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
        }
    }
    
    0 讨论(0)
  • 2020-12-15 23:54

    If you create getters and setters for the attributes, you can use the copyProperties method from Commons BeanUtils.

    0 讨论(0)
  • 2020-12-16 00:03

    This works as long as you have POJOs with their own getters and setters. The method updates obj with non-null values from update. It calls setParameter() on obj with the return value of getParameter() on update:

    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();
                } 
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-16 00:05

    In your very special case it looks like you want a new object that takes the real values from both instances. Here is an implementation that will do that. The method should be add to class A so that it can access the fields.

     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;
     }
    
    0 讨论(0)
  • 2020-12-16 00:09

    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.
            }
          }
        }
      }
    }
    
    0 讨论(0)
  • 2020-12-16 00:10

    Maybe something like

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

    A.merge might return a new A object instead of modifing current.

    0 讨论(0)
提交回复
热议问题