Pregunta

Yo estaba buscando algunos tutoriales que explican sobre Cloneable Java, pero no consiguió ningún enlace buenos, y el desbordamiento de pila se está convirtiendo en la elección más evidente de todos modos.

Me gustaría saber lo siguiente:

  1. Cloneable significa que podemos tener un clon o una copia de los objetos, por implementando la interfaz Cloneable. ¿Cuáles son las ventajas y desventajas de hacer eso?
  2. ¿Cómo se produce la clonación recursiva si el objeto es una objeto compuesto?
¿Fue útil?

Solución

Lo primero que debe saber sobre Cloneable es -. No lo use

Es muy difícil de poner en práctica la clonación con Cloneable derecha, y el esfuerzo no vale la pena.

En lugar de que el uso de algunas otras opciones, como Apache-commons SerializationUtils (deep-clon) o BeanUtils (DOF-clon), o simplemente utilizar un constructor de copia.

Vea aquí de las opiniones del Josh Bloch sobre la clonación con Cloneable, lo que explica la muchos inconvenientes del enfoque. ( Joshua Bloch era un empleado del Sol, y condujo al desarrollo de numerosas características de Java.)

Otros consejos

sí Cloneable es por desgracia sólo una interfaz de marcador, que es:. No define el método clone ()

¿Qué es lo hace, es cambiar el comportamiento de la Object.clone protegido () método, que lanzará una CloneNotSupportedException para las clases que no implementan Cloneable, y realizar una copia superficial miembro en cuanto a las clases que lo hacen.

Incluso si este es el comportamiento que usted está buscando, usted todavía necesita para implementar su propio método clone () con el fin de hacerla pública.

Al implementar su propio clon (), la idea es comenzar con el objeto de crear por super.clone (), que se garantiza que sea de la clase correcta, y realice una población adicional de campos en el caso de una copia superficial no es lo que desea. Llamar a un constructor del clon () sería problemático, ya que esto rompería la herencia en caso de una subclase quiere añadir su propia lógica cloneable adicional; si fuera a super.clone llamada () sería obtener un objeto de la clase equivocada en este caso.

Este enfoque evita cualquier lógica que puede definirse en sus constructores, sin embargo, lo que podría ser problemático.

Otro problema es que las subclases que se olvidan para anular clone () automáticamente hereda la copia superficial predeterminado, lo que probablemente no es lo que desea en caso de estado mutable (que ahora será compartida entre el original y la copia).

La mayoría de los desarrolladores no utilizan Cloneable por estas razones, y simplemente implementar un constructor de copia en su lugar.

Para obtener más información y posibles trampas de Cloneable, le recomiendo el libro Effective Java por Joshua Bloch

  1. Clonación invoca una forma extra-lingüística de la construcción de objetos - sin constructores.
  2. La clonación se requiere para el tratamiento de alguna manera con CloneNotSupportedException -. O molestar código de cliente para tratarla
  3. Los beneficios son pequeñas - que simplemente no tiene que escribir manualmente un constructor copia
  4. .

Por lo tanto, utilizar Cloneable juiciosamente. Que no le da suficientes beneficios en comparación con el esfuerzo que necesita para solicitar que hacer todo bien.

La clonación es un paradigma de programación básica. El hecho de que Java puede haber implementado mal en muchos aspectos no lo hace en absoluto disminuir la necesidad de clonación. Y, es fácil de poner en práctica la clonación que funcionará como quiera que funcione, de poca profundidad, en el fondo, mezclado, lo que sea. Incluso puede utilizar el nombre clon de la función y no aplicar Cloneable si te gusta.

Supongamos que tengo clases A, B, y C, donde B y C son derivados de A. Si tengo una lista de objetos del tipo A como esto:

ArrayList<A> list1;

Ahora, esa lista lata contiene objetos de tipo A, B o C. Usted no sabe qué tipo son los objetos. Por lo tanto, no se puede copiar la lista como esta:

ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    list2.add(new A(a));
}

Si el objeto es en realidad de tipo B o C, no obtendrá el derecho de copia. Y, lo que si A es abstracto? Ahora, algunas personas han sugerido la siguiente:

ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    if(a instanceof A) {
        list2.add(new A(a));
    } else if(a instanceof B) {
        list2.add(new B(a));
    } else if(a instanceof C) {
        list2.add(new C(a));
    }
}

Esta es una muy, muy mala idea. Lo que si se agrega un nuevo tipo derivado? ¿Qué pasa si B o C se encuentran en otro paquete y que no tienen acceso a ellos en esta clase?

¿Qué le gustaría hacer es lo siguiente:

ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    list2.add(a.clone());
}

Mucha gente ha indicado por qué la aplicación Java básica del clon es problemático. Sin embargo, es fácil de superar de esta manera:

En la clase A:

public A clone() {
    return new A(this);
}

En la clase B:

@Override
public B clone() {
    return new B(this);
}

En la clase C:

@Override
public C clone() {
    return new C(this):
}

No estoy implementar Cloneable, simplemente utilizando el mismo nombre de la función. Si no lo hace así, el nombre que otra cosa.

A) No hay un montón de ventajas de clon más de un constructor de copia. Probablemente el más importante es la posibilidad de crear un nuevo objeto del mismo tipo dinámico exacta (suponiendo que el tipo declarado es clonable y tiene un método clone público).

B) El clon defecto crea una copia superficial, y lo seguirá siendo una copia superficial a menos que su aplicación clon que cambia. Esto puede ser difícil, especialmente si su clase tiene campos finales

Bozho es correcto, el clon puede ser difícil hacerlo bien. Un constructor de copia / fábrica servirán mayoría de las necesidades.

¿Cuáles son las desventajas de Cloneable?

La clonación es muy peligroso si el objeto de los cuales está copiando tiene composition.You necesidad de pensar más adelante posible efecto secundario en este caso porque el clon crea copia superficial:

Vamos a decir que tiene un objeto para manejar db manipulación relacionada. Por ejemplo, ese objeto tiene objeto Connection como uno de los bienes.

Así que cuando alguien crea clon del originalObject, el objeto que está siendo creado, vamos digamos, cloneObject. Aquí el originalObject y cloneObject mantienen la misma referencia para el objeto Connection.

Digamos que originalObject cierra el objeto Connection, por lo que ahora el cloneObject no funcionará porque el objeto connection fue compartido entre ellos y que fue cerrado por el actaually originalObject.

problema similar puede ocurrir si deja que dice que quiere clonar un objeto que tiene iostream como una propiedad.

¿Cómo se produce la clonación recursiva si el objeto es un objeto compuesto?

realiza Cloneable copia superficial. El significado es que los datos de objeto original y el objeto clon apuntarán a la misma referencia / memoria. contrario en el caso de copia en profundidad, los datos de la memoria de objeto original se copia a la memoria de objeto clon.

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