11

Recently I faced this question in an Interview:

Write a function to return a deep clone instance of class Drawing

public class Drawing{

  public List<Shape> shapes=new LinkedList<Shape>();

}

where shape is an abstract class having many concrete implementations

public abstract class Shape implements Serializable{

}

Can anyone please tell how to approach this?Do we need to add the clone method in all the concrete implementations?

mahan07
  • 887
  • 4
  • 14
  • 32
  • 8
    The fact that Shape implements Serializable is a hint. The interviewer probably simply expected you to serialize the List and deserialize it, and to create a new Drawing instance referencing the deserialized list. – JB Nizet Jul 16 '15 at 11:18
  • 3
    @JBNizet on the other hand if Shape has transient fields, they will be lost during serialization, but won't be lost if objects are cloned. – AdamSkywalker Jul 16 '15 at 11:28
  • check if this will help http://stackoverflow.com/questions/64036/how-do-you-make-a-deep-copy-of-an-object-in-java – Ravi Jul 16 '15 at 11:34

4 Answers4

3

What you need to do is first serialize the List<Shape> and then deserialize and return a new instance of Drawing with the deserialized List

public static Drawing deepClone(Drawing drawing) {
    try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(drawing.shapes); //Serializes the drawing.shapes

        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais); 
        return new Drawing((LinkedList<Shape>)ois.readObject()); //Deserializing and reading 
    } catch (IOException e) {
        return null;
    } catch (ClassNotFoundException e) {
        return null;
    }
}

Assuming you have a constructor in Drawing which takes in a LinkedList<Shape> as parameter

EDIT

You won't need to add clone() in Shape class as you override clone() method when you implement the Cloneable interface, but according to the question, they want you to create clones using Serializable interface.

Sneh
  • 3,527
  • 2
  • 19
  • 37
  • This is a good answer, however I think it should say something about `transient` fields of `Shape` subclasses, if any. In this case, the deep cloning would not apply to these fields. I mean, as this in an interview question, maybe the OP should mention this and make it clear that it's the trade-off to pay. – fps Jul 16 '15 at 13:24
0

Each sub class of Shape knows how to create a deep copy of itself, because that is one thing Serializable implementations should do. So iterate the list in Drawing and serialize/deserialize the Shape object to create your deep copy of each Shape in the list.

Rey Libutan
  • 5,226
  • 9
  • 42
  • 73
Jeff Anderson
  • 799
  • 7
  • 18
  • Why iterate over the list and serialize `Shape`s one by one? `LinkedList` is also `Serializable`, so serializing and deserializing the list is enough. – fps Jul 16 '15 at 13:22
0

You can also use a library that is faster than serialization methods.

Cloner cloner=new Cloner();

MyClass clone=cloner.deepClone(o);
// clone is a deep-clone of o
Machado
  • 14,105
  • 13
  • 56
  • 97
  • I think he needs to know how to do it using Serializable rather than using a library as it is an interview question and he can't directly say a Library in the interview. – Sneh Jul 16 '15 at 11:43
  • Why not? I think it's clever to suggest using a Library. The OP only needs to trully understand the reason why he would choose it (i.e. how serialization methods works) – Machado Jul 16 '15 at 12:12
0

I would suggest using SerializationUtils.clone from Apach Commons Lang

This method is for deep cloning :

SomeObject cloned = org.apache.commons.lang.SerializationUtils.clone(someObject);

This is a simple way to clone objects but not if you look for performance.

See documentation

JavaDev
  • 307
  • 1
  • 3
  • 16