2015-07-16 8 views
11

Kürzlich stand ich diese Frage in einem Interview:Tiefe Klonen von Sammlungen in Java

Schreiben Sie eine Funktion eine tiefe Klon Instanz der Klasse Zeichnung

public class Drawing{ 

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

} 

wo Form ist eine abstrakte Klasse mit vielen konkreten zurückzukehren Implementierungen

Kann mir bitte jemand sagen, wie man das angehen kann? Müssen wir die Klon-Methode in allen konkreten Implementierungen hinzufügen?

+8

Die Tatsache, dass Shape Serializable implementiert, ist ein Hinweis. Der Interviewer hat wahrscheinlich einfach erwartet, dass Sie die Liste serialisieren und deserialisieren und eine neue Drawing-Instanz erstellen, die auf die deserialisierte Liste verweist. –

+3

@JBNizet andererseits, wenn Shape transiente Felder hat, gehen sie während der Serialisierung verloren, gehen aber nicht verloren, wenn Objekte geklont werden. – AdamSkywalker

+0

prüfen, ob dies hilft http://stackoverflow.com/questions/64036/how-do-you-make-a-deep-copy-of-an-object-in-java – Ravi

Antwort

3

Was müssen Sie tun ist, zuerst die List<Shape> serialisiert und dann deserialisieren und eine neue Instanz von Drawing mit dem deserialisiert 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; 
    } 
} 

zurückkehren Angenommen, Sie einen Konstruktor in Zeichnung haben, die in nimmt a LinkedList<Shape> als Parameter

EDIT

Sie werden nicht clone() in Shape-Klasse hinzufügen müssen, wie Sie clone() Methode überschreiben, wenn Sie den Cloneable-Schnittstelle implementieren, sondern nach der Frage, sie wollen Sie Klonen mit Serializable Schnittstelle erstellen.

+0

Dies ist eine gute Antwort, aber ich denke, es sollte etwas über transiente Felder von 'Shape' Unterklassen, falls vorhanden sagen. In diesem Fall würde das tiefe Klonen nicht für diese Felder gelten. Ich meine, wie dies in einer Interviewfrage gesagt wird, sollte das OP dies vielleicht erwähnen und klarstellen, dass es der Kompromiss ist zu zahlen. –

0

Jede Unterklasse von Shape weiß, wie man eine tiefe Kopie von sich selbst erstellt, denn das ist eine Sache Serializable Implementierungen sollten tun. So iterieren Sie die Liste in Drawing und serialisieren/deserialisieren Sie das Shape Objekt, um Ihre tiefe Kopie jedes Shape in der Liste zu erstellen.

+0

Warum iterieren über die Liste und serialisieren ' Shape's eins nach dem anderen? 'LinkedList' ist auch' Serializable', daher reicht das Serialisieren und Deserialisieren der Liste aus. –

0

Sie können auch use a library, die schneller als Serialisierungsmethoden ist.

Cloner cloner=new Cloner(); 

MyClass clone=cloner.deepClone(o); 
// clone is a deep-clone of o 
+0

Ich denke, er muss wissen, wie man es mit Serializable macht, anstatt eine Bibliothek zu benutzen, da es sich um eine Interviewfrage handelt und er im Interview nicht direkt eine Bibliothek sagen kann. – Sneh

+0

Warum nicht? Ich denke, es ist klug, eine Bibliothek zu empfehlen. Das OP muss nur den Grund verstehen, warum er es wählen würde (d. H.wie Serialisierungsmethoden funktionieren) – Machado

0

würde ich vorschlagen, SerializationUtils.clone von Apach Commons Lang

Diese Methode ist für tiefes Klonen:

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

Dies ist eine einfache Möglichkeit, Objekte zu klonen, aber nicht, wenn man sucht Performance.

See documentation

+1

Dies ist keine Antwort ... Bitte erläutern Sie, warum Sie das vorschlagen, die Vorteile und die Nachteile der Verwendung. Vielleicht sogar zeigen einige Beispiel-Code – Mackiavelli

+0

gerade meine Antwort bearbeitet – JavaDev