Estaba buscando algunos tutoriales que explicaran sobre Java Cloneable
, pero no obtuve ningún buen enlace, y Stack Overflow se está volviendo una opción más obvia de todos modos.
Me gustaría saber lo siguiente:
Cloneable
significa que podemos tener un clon o una copia de objetos, implementando laCloneable
interfaz. ¿Cuáles son las ventajas y desventajas de hacer eso?- ¿Cómo ocurre la clonación recursiva si el objeto es un objeto compuesto?
Respuestas:
Lo primero que debe saber
Cloneable
es: no lo use.Es muy difícil implementar la clonación con
Cloneable
derechos y el esfuerzo no vale la pena.En lugar de eso, use algunas otras opciones, como apache-commons
SerializationUtils
(clon profundo) oBeanUtils
(clon superficial), o simplemente use un constructor de copia.Consulte aquí las opiniones de Josh Bloch sobre la clonación con
Cloneable
, lo que explica los muchos inconvenientes del enfoque. ( Joshua Bloch era un empleado de Sun y dirigió el desarrollo de numerosas funciones de Java).fuente
static
métodos en las interfaces, así que solo proporcione unstatic WhatEverTheInterface copy(WhatEverTheInterface initial)
? pero me pregunto qué le da esto, ya que copia campos de un objeto mientras clona, pero una interfaz define solo métodos. ¿le importaria explicar?Lamentablemente, Cloneable es solo una interfaz de marcador, es decir: no define el método clone ().
Lo que sí hace es cambiar el comportamiento del método protegido Object.clone (), que lanzará una CloneNotSupportedException para las clases que no implementan Cloneable, y realizará una copia superficial de miembros para las clases que sí lo hagan.
Incluso si este es el comportamiento que está buscando, necesitará implementar su propio método clone () para hacerlo público.
Al implementar su propio clone (), la idea es comenzar con el objeto creado por super.clone (), que está garantizado para ser de la clase correcta, y luego hacer cualquier población adicional de campos en caso de que una copia superficial no sea lo que usted quiere. Llamar a un constructor desde clone () sería problemático ya que esto rompería la herencia en caso de que una subclase quiera agregar su propia lógica clonable adicional; si llamara a super.clone () obtendría un objeto de la clase incorrecta en este caso.
Sin embargo, este enfoque evita cualquier lógica que pueda definirse en sus constructores, lo que podría ser potencialmente problemático.
Otro problema es que las subclases que se olvidan de anular clone () heredarán automáticamente la copia superficial predeterminada, que probablemente no sea lo que desea en caso de estado mutable (que ahora se compartirá entre la fuente y la copia).
La mayoría de los desarrolladores no usan Cloneable por estas razones y simplemente implementan un constructor de copia en su lugar.
Para obtener más información y las posibles dificultades de Cloneable, recomiendo encarecidamente el libro Effective Java de Joshua Bloch.
fuente
Por lo tanto, use Cloneable con prudencia. No le brinda suficientes beneficios en comparación con el esfuerzo que necesita para aplicar para hacer todo bien.
fuente
La clonación es un paradigma de programación básico. El hecho de que Java pueda haberlo implementado de manera deficiente de muchas maneras no disminuye en absoluto la necesidad de clonación. Y, es fácil implementar la clonación que funcionará como usted quiera que funcione, superficial, profunda, mixta, lo que sea. Incluso puede usar el nombre clon para la función y no implementar Cloneable si lo desea.
Supongamos que tengo las clases A, B y C, donde B y C se derivan de A. Si tengo una lista de objetos de tipo A como esta:
Ahora, esa lista puede contener objetos de tipo A, B o C. No sabe de qué tipo son los objetos. Entonces, no puede copiar la lista de esta manera:
Si el objeto es en realidad de tipo B o C, no obtendrá la copia correcta. ¿Y si A es abstracto? Ahora, algunas personas han sugerido esto:
Esta es una muy, muy mala idea. ¿Qué pasa si agrega un nuevo tipo derivado? ¿Qué pasa si B o C están en otro paquete y no tiene acceso a ellos en esta clase?
Lo que le gustaría hacer es esto:
Mucha gente ha indicado por qué la implementación básica de Java del clon es problemática. Pero, se supera fácilmente de esta manera:
En clase A:
En clase B:
En clase C:
No estoy implementando Cloneable, solo uso el mismo nombre de función. Si no le gusta, asígnele otro nombre.
fuente
R) No hay muchas ventajas de clonar sobre un constructor de copias. Probablemente, el más grande es la capacidad de crear un nuevo objeto del mismo tipo dinámico exacto (asumiendo que el tipo declarado es clonable y tiene un método de clonación público).
B) El clon predeterminado crea una copia superficial, y seguirá siendo una copia superficial a menos que la implementación de su clon cambie eso. Esto puede ser difícil, especialmente si tu clase tiene campos finales.
Bozho tiene razón, clonar puede ser difícil de hacer bien. Un constructor / fábrica de copias satisfará la mayoría de las necesidades.
fuente
¿Cuáles son las desventajas de Cloneable?
La clonación es muy peligrosa si el objeto que está copiando tiene composición. Debe pensar en los posibles efectos secundarios a continuación en este caso porque la clonación crea una copia superficial:
Digamos que tiene un objeto para manejar la manipulación relacionada con la base de datos. Digamos, ese objeto tiene
Connection
objeto como una de las propiedades.Así que cuando alguien crea clon
originalObject
, el objeto que está siendo creado, vamos a decir,cloneObject
. Aquí eloriginalObject
ycloneObject
tiene la misma referencia para elConnection
objeto.Digamos que
originalObject
cierra elConnection
objeto, por lo que ahoracloneObject
no funcionará porque elconnection
objeto fue compartido entre ellos y en realidad fue cerrado pororiginalObject
.Puede ocurrir un problema similar si digamos que desea clonar un objeto que tiene IOStream como propiedad.
¿Cómo ocurre la clonación recursiva si el objeto es un objeto compuesto?
Cloneable realiza copia superficial. El significado es que los datos del objeto original y el objeto clonado apuntarán a la misma referencia / memoria. al contrario, en el caso de la copia profunda, los datos de la memoria del objeto original se copian en la memoria del objeto clonado.
fuente
Cloneable
no realiza una copia, loObject.clone
hace. "Los datos de la memoria del objeto original se copian en la memoria del objeto clonado" es precisamente lo queObject.clone
hace. Necesita hablar sobre la memoria de los objetos referenciados para describir la copia profunda.