3

Actually, I searched the solution for that in web. I also found Copy an object in Java. In my object, there are a lot mapping. Even I use Cloneable and Copy Constructor, I still need to copy for each fields?

My requirement is to know which data changed between Old Object and New Object.

My object Example Tree :

MotorProposal
    - startDate : Date              ---> can change
    - endDate : Date                ---> can change
    - customer : Cutomer
    - vehicleList : List<Vehicle>   ---> can chnage
        - carNo : String            ---> can change
        - loading : int             ---> can change
        - cubicCapacity : int       ---> can chnage
        - driver : Driver           ---> can change
            - fullName : String     ---> can change
            - address : Stirng      ---> can change
            - license : Stirng      ---> can change
            - expYear : int         ---> can change
        - model : Model

        -there other fields

    -there other fields

Is there another way to create new Instance with the same value without copying for each field?

My expected program

MotorProposal oldProposal = --> come from DB
MotorProposal newProposal = org.someapi.ObjectUtil.newInstance(oldProposal);

Update

Currently, I solve this case Martin Dinov suggested. As below.

ObjCopy.java

public class ObjCopy {
    public static Serializable newInstance(Serializable obj) {
        Serializable result = null;
        try {
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(buffer);
            oos.writeObject(obj);
            oos.flush();
            oos.close();

            ByteArrayInputStream in = new ByteArrayInputStream(buffer.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(in);
            return (Serializable)ois.readObject();
        } catch (Exception e) {
            //do nothing
            e.printStackTrace();
        }
        return result;
    } 
}

Test.java

public class Test {
    public static void main(String[] args) {
        Country country = new Country();
        country.setName("Myanmar");
        Province province_1 = new Province();
        province_1.setCountry(country);
        province_1.setName("Yangon");

        Province province_2 = (Province)ObjCopy.newInstance(province_1);
        province_2.getCountry().setName("USA");
        System.out.println(province_1.getName() + "-" + province_1.getCountry().getName());
        System.out.println(province_2.getName() + "-" + province_2.getCountry().getName());
    }
}   

Output

Yangon-Myanmar
Yangon-USA
Community
  • 1
  • 1
Zaw Than oo
  • 9,651
  • 13
  • 83
  • 131
  • How about SerializationUtils.clone [http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/SerializationUtils.html] metod..?? – Siva Jan 08 '14 at 08:06
  • What part of the answers to the Q you link to are not answering your question? No, there's no magical way to not copy a field and have it be copied. Also be aware you need to do a *deep copy*; you'll need to copy the *contents* of your lists and not just the reference to the list. (As noted in the comment above, you could use a serialization technique, but you're adding a lot of overhead and possibly a giant third party dependency) – Brian Roach Jan 08 '14 at 08:06
  • @CycDemo If your aim is only to know what data of your model object is modified why not use PropertyChangeListeners instead of all the hassles of deep copy? Please refer http://www.vogella.com/tutorials/DesignPatternObserver/article.html for an example. – thiyaga Jan 08 '14 at 08:27

2 Answers2

3

How about Yoni Roit's second proposal from the Stackoverflow link you provide? In other words, serialize and then deserialize the object - so this will result in deep copying your object byte-wise. You need to have your class implement Serializable. As long as all class fields can be serialized, this approach should work. However, serializing and deserializing objects can be quite slow apparently - probably not an issue if you want to do this out of convenience, rather than out of efficiency. Here's a simple example of re-creating a new ArrayList:

    ArrayList<Integer> foo = new ArrayList<Integer>();
    foo.add(5);
    foo.add(3);
    foo.add(1);
    ArrayList<Integer> obj = null;
    // Write the object out to a byte array
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream out = new ObjectOutputStream(bos);
    out.writeObject(foo);
    out.flush();
    out.close();

    // Make an input stream from the byte array and read
    // a copy of the object back in.
    ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(
            bos.toByteArray()));
    obj = (ArrayList<Integer>)in.readObject();

In your case, you'd want to type-cast to your specific class of course. This way you don't have to explicitly copy each field in the class.

Martin Dinov
  • 8,757
  • 3
  • 29
  • 41
0

No CyCDemo, there are a lot of issues about the Cloneable interface and the reason of and the reasons why Java has not implemented a deep copy.

In any case get an eye there:

https://code.google.com/p/cloning/

venergiac
  • 7,469
  • 2
  • 48
  • 70