2011-06-17 14 views
9

come ho capito, il metodo clone() ci dà la possibilità di copiare oggetti (senza referenze) in Java. Ma leggo anche che la copia è superficiale. Allora, qual è il punto? Quale capacità mi dà il metodo clone(), che una semplice asserzione no?metodo clone() in Java

risposta

21

La differenza è che è possibile modificare l'oggetto clonato senza modificare l'oggetto originale.

Point p = new Point(1,2); 
Point p2 = p.clone(); 
Point p3 = p; 
p2.x = 5; 
p3.y = 7; 

La variazione p3 non feed back al p, mentre la variazione su p2 non lo fa.

Vediamo come la situazione è dopo le singole dichiarazioni (assumendo 1, 2, 5, 7 sarebbe oggetti):

Point p = new Point(1,2); 

      .-----. .-----. 
p -----> | x -+--> | 1 | 
      |  | '-----' 
      |  | .-----. 
      | y -+--> | 2 | 
      '-----' '-----' 


Point p2 = p.clone(); 

      .-----. .-----. .-----. 
p -----> | x -+--> | 1 | <--+- x | <----- p2 
      |  | '-----' |  | 
      |  | .-----. |  | 
      | y -+--> | 2 | <--+- y | 
      '-----' '-----' '-----' 

Point p3 = p; 

      .-----. .-----. .-----. 
p -----> | x -+--> | 1 | <--+- x | <----- p2 
      |  | '-----' |  | 
      |  | .-----. |  | 
p3 -----> | y -+--> | 2 | <--+- y | 
      '-----' '-----' '-----' 


p2.x = 5; 

      .-----. .-----. .-----. .-----. 
p -----> | x -+--> | 1 | | x -+--> | 5 | 
      |  | '-----' |  | '-----' 
      |  | .-----. |  | 
p3 -----> | y -+--> | 2 | <--+- y | <----- p2 
      '-----' '-----' '-----' 


p3.y = 7; 

      .-----. .-----. .-----. .-----. 
p -----> | x -+--> | 1 | | x -+--> | 5 | 
      |  | '-----' |  | '-----' 
      |  | .-----. |  | 
p3 -----> | y | | 2 | <--+- y | <----- p2 
      '--+--' '-----' '-----' 
       |  .-----. 
       '---> | 7 | 
        '-----' 
+0

Grazie, ma non capisco perché p2.x non cambierà nulla in p. È giusto che abbiamo 2 oggetti diversi, ma sono punti per lo stesso xey (perché la copia superficiale). Cosa mi manca? – Tom

+0

L'assegnazione (nelle ultime due righe) cambia a cosa puntano 'x' e' y'. Anche se 'p.x' e' p2.x' hanno lo stesso valore (riferito allo stesso oggetto), sono variabili diverse e assegnandole a una non cambia l'altra. (In questo caso non sono nemmeno oggetti, ma valori primitivi, ma la stessa cosa sarebbe valida se fossero oggetti.) –

+0

In questo esempio non vediamo la differenza tra la clonazione superficiale e quella profonda. –

4

Un semplice compito creerà semplicemente un alias per l'oggetto. Con clone(), ogni membro di attributo verrà anche inizializzato nell'oggetto clone. Tuttavia, se i membri degli attributi hanno essi stessi più oggetti contenuti al loro interno, quelli non saranno copiati.

7

Un incarico copia il riferimento di un'istanza a una variabile. L'operazione clone clonerà l'istanza (e assegnerà un riferimento al clone).

Con assegnazione, vi ritroverete con multipla variabili indicando una oggetto, con la clonazione avrete più variabili che contengono riferimenti di multipla oggetti.

SomeCloneable a = new SomeCloneable(); 
SomeCloneable b = a;      // a and b point to the same object 

/* versus */ 

SomeCloneable a = new SomeCloneable(); 
SomeCloneable b = a.clone();    // a and b point to the different objects 
+0

'Cloneable' non fa il' clone) 'metodo pubblico (, però. Dovrai dichiarare il tuo 'a' e' b' come 'SomeCloneable'. –

+0

@ Paŭlo Ebermann - buona presa, grazie, la correggerò! –

3

copia superficiale è la predefinita per oggetto. puoi ignorare il clone per fare una copia profonda.

1

per clonare in profondità è necessario implementare Cloneable e sovrascrivere clone()

public class MyClass implements Cloneable { 

private Object attr = new Object(); 

@Override 
public Object clone() throws CloneNotSupportedException { 
    MyClass clone = (MyClass)super.clone(); 
    clone.attr = new Object(); 
    return clone; 
} 

@Override 
public String toString() { 
    return super.toString()+", attr=" + attr; 
} 

public static void main(String[] args) throws Exception { 
    MyClass x = new MyClass(); 
    System.out.println("X="+x); 
    MyClass y = (MyClass)x.clone(); 
    System.out.println("Y="+y); 
} 

}