Pregunta

En Effective Java, el autor afirma que:

Si implementa una clase Cloneable, método clone del objeto devuelve una campo por campo copia del objeto; de lo contrario se lanza CloneNotSupportedException.

Lo que me gustaría saber es lo que quiere decir con copia campo por campo. ¿Quiere decir que si la clase tiene X bytes en la memoria, se acaba de copiar esa parte de memoria? Si es así, puedo suponer que todos los tipos de valores de la clase original se copiarán en el nuevo objeto?

class Point implements Cloneable{
    private int x;
    private int y;

    @Override
    public Point clone() {
        return (Point)super.clone();
    }
}

Si lo hace Object.clone() es un campo por campo copia de la clase Point, diría que yo no tenga que copiar de manera explícita campos x y y, siendo que incluya la palabra clave será más que suficiente para hacer una clon de la clase Point. Es decir, el siguiente fragmento de código es redundante:

@Override
public Point clone() {
    Point newObj = (Point)super.clone();
    newObj.x = this.x; //redundant
    newObj.y = this.y; //redundant
}

Estoy en lo cierto?

Yo sé referencias del objeto clonado señalarán automáticamente a donde las referencias originales del objeto señalaron, no estoy seguro de lo que ocurre específicamente con los tipos de valor. Si alguien pudiera indicar claramente cuál especificación del algoritmo de Object.clone() es (en lenguaje sencillo) que sería genial.

¿Fue útil?

Solución

Sí, un campo por campo copia sí significa que cuando se crea el nuevo objeto (clonado), la JVM copiará el valor de cada campo del objeto original en el objeto clonado. Desafortunadamente esto significa que usted tiene una copia superficial. Si desea una copia en profundidad, se puede reemplazar el método de clonación.

class Line implements Cloneable {

    private Point start;
    private Point end;

    public Line() {
        //Careful: This will not happen for the cloned object
        SomeGlobalRegistry.register(this);
    }

    @Override
    public Line clone() {
        //calling super.clone is going to create a shallow copy.
        //If we want a deep copy, we must clone or instantiate
        //the fields ourselves
        Line line = (Line)super.clone();
        //assuming Point is cloneable. Otherwise we will
        //have to instantiate and populate it's fields manually
        line.start = this.start.clone();
        line.end = this.end.clone;
        return line;
    }
}

También una cosa más importante acerca de la clonación es, el constructor del objeto clonado es nunca invocó (sólo los campos se copian). Así que si el constructor inicializa un objeto externo, o registra este objeto con algún registro, entonces eso no sucederá para el objeto clonado.

Yo personalmente prefiero no usar la clonación de Java. En lugar Por lo general crear mis propios métodos "duplicación".

Otros consejos

Esto significa una copia superficial - los campos se copian, pero si usted tiene alguna referencia, lo que estos puntos no se copia - Tendrá dos referencias al mismo objeto, una en el objeto antiguo y uno en el nuevo, objeto clonado. Sin embargo, para los campos que tienen tipos primitivos, el campo es los datos en sí, por lo que se copian sin tener en cuenta.

newObj.x = this.x; //redundant
newObj.y = this.y; //redundant

Así es -. Estos son redundantes, puesto que ellos ya han sido copiados por el clon de Object () método

Pensando en ello como una copia de datos es correcta. Los tipos primitivos se copian, y las referencias también se copian para que apunten al mismo objeto. Por ejemplo,

class A implements Cloneable {
  Object someObject;
}

A a = new A();
a.someObject = new Object();

A cloneA = (A)a.clone();
assert a.someObject==cloneA.someObject;

El clon superficial realiza por defecto copia de valores. Para valores primitivos, esto es suficiente y no es necesario ningún trabajo extra.

Para los objetos, las aguas poco profundas ejemplar significa copiar sólo la referencia. Por lo tanto, en estos casos generalmente se necesita una copia profunda. La excepción a esto es cuando la referencia apunta a un objeto inmutable. Los objetos inmutables no pueden tener su aparente estado cambiado, por lo tanto, sus referencias se pueden copiar en torno segura. Por ejemplo, esto se aplica a String, Integer, Float, enumeraciones (si no se hizo mutable por error).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top