make implement example java clone

implement - java deep clone object



Recomendación de utilidad de clonación profunda (8)

He usado esta biblioteca de cloning y la encontré bastante útil. Dado que tenía algunas limitaciones (necesitaba un control más detallado sobre el proceso de clonación: qué campo, en qué contexto y qué tan profundamente debía clonarse, etc.), creé una versión extendida de él. Usted controla la clonación de los campos anotándolos en la clase de entidad.

Solo para darle un sabor, aquí hay una clase de ejemplo:

public class CloneMePlease { @Clone(Skip.class) String id3 = UUID.randomUUID().toString(); @Clone(Null.class) String id4 = UUID.randomUUID().toString(); @Clone(value = RandomUUID.class, groups=CustomActivationGroup1.class) String id5 = UUID.randomUUID().toString(); @Clone.List({ @Clone(groups=CustomActivationGroup2.class, value=Skip.class), @Clone(groups=CustomActivationGroup3.class, value=Copy.class)}) Object activationGroupOrderTest = new Object(); @Clone(LongIncrement.class) long version = 1l; @PostClone private void postClone(CloneMePlease original, @CloneInject CloneInjectedService service){ //do stuff with the original source object in the context of the cloned object //you can inject whatewer service you want, from spring/guice to perform custom logic here } }

Más detalles aquí: https://github.com/mnorbi/fluidity-cloning

También hay una extensión específica de hibernación en caso de que la necesite.

¿Hay alguna utilidad para la clonación profunda para colecciones Java?

  • Arrays
  • Liza
  • Mapas

NOTA: prefiera alguna solución sin uso de serialización, pero con el uso del método Object.clone (). Puedo estar seguro de que mi objeto personalizado implementará el método clone () y solo usaré las clases estándares de Java que son clonables ...


La clonación superficial de una colección es fácil, pero si quieres clonar en profundidad, una biblioteca probablemente te sirva mejor que codificarla manualmente (ya que también quieres clonar los elementos dentro de la colección).

Al igual que esta respuesta , utilicé la https://github.com/kostaskougios/cloning y específicamente la evalué contra XStream (que puede "clonar" serializando y luego deserializando) y la serialización binaria. Aunque XStream es muy rápido en la serialización hacia / desde xml, Cloner es mucho más rápido en la clonación:

0.0851 ms: xstream (clon mediante serialización / deserialización)
0.0223 ms: serialización binaria (clon mediante serialización / deserialización)
0.0017 ms: clonador
* tiempo promedio para clonar un objeto simple (dos campos) y ningún constructor público predeterminado. Ejecutar 10,000 veces.

Además de ser rápido, aquí hay más razones para elegir cloner:

  1. realiza un clon profundo de cualquier objeto (incluso aquellos que no escribes)
  2. no tiene que mantener su método clone () actualizado cada vez que agrega un campo
  3. puedes clonar objetos que no tienen un constructor público predeterminado
  4. trabaja con Spring
  5. (optimización) no clona objetos inmutables conocidos (como Integer, String, etc.)
  6. fácil de usar. Ejemplo:

    cloner.deepClone (anyObject);


Soy el creador de la cloner lib, la que presentó Brad. Esta es una solución para clonar objetos sin tener que escribir ningún código adicional (sin necesidad de objetos serializables o método impl clone ())

Es bastante rápido como dijo Brad, y recientemente subí una versión que es incluso más rápida. Tenga en cuenta que implementar manualmente un método clone () será más rápido que clonear lib, pero luego tendrá que escribir mucho código.

Cloner lib me ha funcionado bastante bien, ya que lo estoy usando en una implementación de caché para un sitio con mucho tráfico (~ 1 millón de solicitudes / día). La memoria caché debe clonar aproximadamente 10 objetos por solicitud. Es bastante confiable y estable. Pero tenga en cuenta que la clonación no está exenta de riesgos. La lib se puede configurar para imprimir en cada instancia de clase que clona durante el desarrollo. De esta forma puede verificar si clona lo que cree que debería clonarse: los gráficos de objetos pueden ser muy profundos y pueden contener referencias a una cantidad sorprendentemente grande de objetos. Con clone lib, puede indicarle que no clone los objetos que no desea, es decir, singletons.


Todos los enfoques para copiar objetos en Java tienen serios defectos:

Clon

  1. El método clone () está protegido, por lo que no puede llamarlo directamente a menos que la clase en cuestión lo anule con un método público.
  2. clone () no llama al constructor. Cualquier constructor. getClass() memoria, asignará el campo de class interna (que puede leer a través de getClass() ) y copiará los campos del original.

Para más problemas con clone (), vea el ítem 11 del libro de Joshua Bloch " Effective Java, Second Edition "

Publicar por fascículos

Serializar es aún peor; tiene muchos de los defectos del clone() y algo más. Joshua tiene un capítulo completo con cuatro elementos solo para este tema.

Mi solución

Mi solución es agregar una nueva interfaz a mis proyectos:

public interface Copyable<T> { T copy (); T createForCopy (); void copyTo (T dest); }

El código se ve así:

class Demo implements Copyable<Demo> { public Demo copy () { Demo copy = createForCopy (); copyTo (copy); return copy; } public Demo createForCopy () { return new Demo (); } public void copyTo (Demo dest) super.copyTo (dest); ...copy fields of Demo here... } }

Desafortunadamente, tengo que copiar este código a todos mis objetos, pero siempre es el mismo código, así que puedo usar una plantilla de editor de Eclipse. Ventajas:

  1. Puedo decidir qué constructor llamar y cómo inicializar qué campo.
  2. La inicialización ocurre en un orden determinista (clase raíz a clase de instancia)
  3. Puedo reutilizar objetos existentes y sobrescribirlos
  4. Escriba seguro
  5. Singletons permanecen solteros

Para tipos de Java estándar (como colecciones, etc.), utilizo una clase de utilidad que puede copiarlos. Los métodos tienen indicadores y devoluciones de llamada, por lo que puedo controlar qué tan profunda debe ser una copia.


Una posibilidad es usar la serialización :

Apache Commons proporciona SerializationUtils


Use la serialización y luego la deserialización, pero tenga en cuenta que este enfoque solo funciona con clases serializables sin campos transitorios. Además, sus singletons ya no serán singletons.


Creo que la respuesta verde anterior fue mala , ¿por qué puedes preguntar?

  • Agrega mucho código
  • Requiere que liste todos los campos que se copiarán y haga esto
  • Esto no funcionará para las Listas cuando se usa clone () (Esto es lo que clone () para HashMap dice: Devuelve una copia superficial de esta instancia de HashMap: las teclas y values ​​ellos mismos no están clonados.) Así que terminas haciéndolo manualmente (esto hace llorar)

Ah, y por cierto la serialización también es mala, es posible que tengas que agregar Serializable por todas partes (esto también me hace llorar).

Entonces, cuál es la solución:

Biblioteca de clonación profunda de Java La biblioteca de clonación es una biblioteca de java pequeña, de código abierto (licencia de apache) que clona objetos en profundidad. Los objetos no tienen que implementar la interfaz Cloneable. Efectivamente, esta biblioteca puede clonar CUALQUIER objeto Java. Se puede usar, por ejemplo, en implementaciones de caché, si no desea que se modifique el objeto en caché o cuando quiera crear una copia profunda de los objetos.

Cloner cloner=new Cloner(); XX clone = cloner.deepClone(someObjectOfTypeXX);

Compruébelo en https://github.com/kostaskougios/cloning


Una forma general de clonar una colección arbitraria consiste en serializarla en una secuencia y luego volver a leerla en una nueva colección. Va a rehidratar objetos completamente nuevos que no tienen ninguna relación con los anteriores, que no sean copias idénticas.

Consulte la respuesta de Bruno para obtener un enlace a las clases de utilidad de serialización de Apache Commons , que será muy útil si esta es la ruta que decide tomar.