2012-03-29 11 views
0

Einige Frage auf Java-Grundlagen, die unten Funktion gibt ein Objekt vom Knotentypzurückgegebene Objekt Modifikation java

class DS{ 
    public Node getNode(int index){ 
     return nodeList.get(index); 
    } 
} 

public void test1(){ 
    DS ds = new DS(); 
    Node node = ds.getNode(3); 
    // will the change in node variable(of test1()) change the actual Node object in ds? 
    // Is there a simple way to create a copy to prevent source node's data modification? 
} 

Vielen Dank im Voraus.

Antwort

2

Die getNode() Methode für die DS-Klasse gibt eine Referenz an den in nodeList gespeicherten Knoten zurück. Wenn also Ihre Klasse Node mutiert werden kann (über Setter-Methoden oder direkten Zugriff auf ihre Felder), dann wird Ihr Code in test1 die zugrunde liegende (und jetzt freigegebene) Node-Referenz ändern.

Wenn Sie den zurückgegebenen Knoten vom Knoten in Ihrem Datenspeicher trennen möchten, können Sie zuerst clone. Ihre Knotenklasse muss Cloneable implementieren und die clone()-Methode überschreiben. Wenn Sie nur Primitiven in Knoten haben, dann können Sie einfach tun:

public Object clone() 
{ 
    return super.clone(); 
} 

Wenn Sie andere Objekte in Knoten haben, dann wird nur der Standard Klonvorgang eine flache Kopie machen, und Sie machen müssen, um Ihre Klon Methode umfangreicher, so dass es tiefe Kopien macht. Aus dem Javadoc für Object.clone():

Per Konvention sollte das Objekt, das von dieser Methode zurückgegeben wird, unabhängig von diesem Objekt sein (das geklont wird).Um diese Unabhängigkeit zu erreichen, kann es notwendig sein, ein oder mehrere Felder des von super.clone zurückgegebenen Objekts zu ändern, bevor es zurückgegeben wird. In der Regel bedeutet dies, dass alle änderbaren Objekte kopiert werden, die die interne "Tiefenstruktur" des geklonten Objekts bilden, und die Referenzen auf diese Objekte durch Referenzen auf die Kopien ersetzt werden. Wenn eine Klasse nur primitive Felder oder Verweise auf unveränderbare Objekte enthält, müssen in der Regel keine Felder in dem von super.clone zurückgegebenen Objekt geändert werden.

Die Änderung wird an Ihrer DS Klasse:

public Node getNode(int index){ 
    return (Node) nodeList.get(index).clone(); 
} 
1

Ja, das Ändern der node in test1() wird das Objekt ändern, das in der ds Liste ist. Das liegt daran, dass es sich um einen Verweis auf dasselbe Objekt handelt.

Wenn Sie node ändern möchten, ohne das Original zu beeinträchtigen, müssen Sie eine Kopie erstellen - z. B. tun Sie new Node() und kopieren Sie dann alle Felder von der alten auf die neue. Sie können auch die Schnittstelle Cloneable implementieren und die clone()-Methode der Object-Klasse verwenden. Oder geben Sie Node einen Konstruktor, der ein anderes Node als ein Argument nimmt und seine Daten kopiert.

+0

FYI Der Name an einen Konstruktor gegeben, das ein anderes Objekt des gleichen Typs akzeptiert und erstellt eine Kopie von ihm (wenig überraschend) eine „Kopie ist Konstruktor " – Bohemian

+0

Reicht die vorhandene Standardklonmethode nicht aus? sollte ich das explizit implementieren? – sravanreddy001

+1

@mrb - Wenn Sie 'clone()' für ein Objekt aufrufen, das 'Cloneable' nicht implementiert, erhalten Sie eine' CloneNotSupportedException'. Referenz: Javadocs für 'Cloneable'. –

0

Ja. Sie erhalten einfach eine Referenz auf das (gleiche) Node-Objekt. Alle daran vorgenommenen Änderungen spiegeln sich überall wider (Threading-Probleme ungeachtet).

zurückzukehren eine Kopie der Knoten stattdessen tun:

erstellen "Copykonstruktor":

public Node(Node node) { 
    // Copy all the fields across 
    this.field1 = node.field1; 
    this.field2 = node.field2; 
    // etc 
} 

Von Ihrer Methode, geben Sie den Copy-Konstruktor eine Kopie mit:

public Node getNode(int index){ 
    return new Node(nodeList.get(index)); 
} 

Dieses Codemuster wird als "safe publishing" bezeichnet - Ihre API stellt dem Aufrufer Objekte sicher zur Verfügung, und Ihre Klasse ist vor Unfällen geschützt Ental Modifikation seines Zustandes (dh Felder).

+0

Was kann ich tun, um ein anderes Objekt zurückzugeben? – sravanreddy001

+0

Ich würde * nicht * 'Clonable' verwenden. Ich würde einfach eine Kopie Konstruktor machen - siehe bearbeitete Antwort – Bohemian

0

Wie andere erwähnt haben, ist die Antwort Ja.

Eine noch nicht erwähnte Option ist das Node-Objekt immutable.

+0

Es ist nicht, dass ich keine Änderungen vornehmen möchte, Ich möchte Änderungen vornehmen, aber ich brauche eine Kopie davon nicht original. Wenn wir also kein neues Schlüsselwort verwenden (einige davon im Code), ist es nur ein Verweis auf das Objekt. ist das richtig? – sravanreddy001

Verwandte Themen