Considere el siguiente código:
DummyBean dum = new DummyBean();
dum.setDummy("foo");
System.out.println(dum.getDummy()); // prints 'foo'
DummyBean dumtwo = dum;
System.out.println(dumtwo.getDummy()); // prints 'foo'
dum.setDummy("bar");
System.out.println(dumtwo.getDummy()); // prints 'bar' but it should print 'foo'
Por lo tanto, quiero copiar el dum
que dumtwo
y el cambio dum
sin afectar al dumtwo
. Pero el código anterior no está haciendo eso. Cuando cambio algo dum
, dumtwo
también está ocurriendo el mismo cambio .
Supongo que, cuando digo dumtwo = dum
, Java copia solo la referencia . Entonces, ¿hay alguna forma de crear una copia nueva dum
y asignarla dumtwo
?
Básico: Copia de objetos en Java.
Supongamos que un objeto
obj1
, que contiene dos objetos, contieneObj1 y contenidoObj2 .copia superficial: la copia
superficial crea una nueva
instance
clase de la misma clase y copia todos los campos a la nueva instancia y la devuelve. La clase de objeto proporciona unclone
método y proporciona soporte para la copia superficial.Copia profunda : una copia profunda ocurre cuando un objeto se copia junto con los objetos a los que se refiere . La imagen a continuación se muestra
obj1
después de que se haya realizado una copia profunda. No solo seobj1
ha copiado , sino que también se han copiado los objetos que contiene. Podemos usarJava Object Serialization
para hacer una copia profunda. Desafortunadamente, este enfoque también tiene algunos problemas ( ejemplos detallados ).Posibles problemas:
clone
es difícil de implementar correctamente.Es mejor usar copias defensivas , constructores de copias (como @egaga reply) o métodos estáticos de fábrica .
clone()
método público , pero no conoce el tipo de objeto en tiempo de compilación, entonces tiene un problema. Java tiene una interfaz llamadaCloneable
. En la práctica, debemos implementar esta interfaz si queremos hacer un objetoCloneable
.Object.clone
está protegido , por lo que debemos anularlo con un método público para que sea accesible.clone()
método de todas las variables de objeto miembro también hace una copia profunda, esto es demasiado arriesgado de suponer. Debe controlar el código en todas las clases.Por ejemplo, org.apache.commons.lang.SerializationUtils tendrá un método para clonar en profundidad usando la serialización ( Fuente ). Si necesitamos clonar Bean, entonces hay un par de métodos de utilidad en org.apache.commons.beanutils ( Fuente ).
cloneBean
clonará un bean en función de los captadores y establecedores de propiedades disponibles, incluso si la clase de bean no implementa Cloneable.copyProperties
copiará los valores de propiedad del bean de origen al bean de destino para todos los casos en que los nombres de propiedad sean los mismos.fuente
En el paquete
import org.apache.commons.lang.SerializationUtils;
hay un método:Ejemplo:
fuente
Serializable
Solo sigue lo siguiente:
y donde quiera obtener otro objeto, simplemente realice la clonación. p.ej:
fuente
¿Por qué no hay una respuesta para usar Reflection API?
Es muy simple
EDITAR: Incluir objeto hijo a través de recursión
fuente
Class A { B child; } Class B{ A parent; }
class car { car car = new car(); }
Utilizo la biblioteca JSON de Google para serializarla y luego crear una nueva instancia del objeto serializado. Hace una copia profunda con algunas restricciones:
no puede haber referencias recursivas
no copiará matrices de tipos dispares
las matrices y las listas deben escribirse o no encontrará la clase para instanciar
es posible que necesite encapsular cadenas en una clase que declare
También uso esta clase para guardar las preferencias del usuario, las ventanas y otras cosas que se deben volver a cargar en tiempo de ejecución. Es muy fácil de usar y efectivo.
fuente
Sí, solo estás haciendo referencia al objeto. Puede clonar el objeto si implementa
Cloneable
.Mira este artículo wiki sobre cómo copiar objetos.
Consulte aquí: copia de objetos
fuente
Agrega
Cloneable
y debajo del código a tu claseUtilizar este
clonedObject = (YourClass) yourClassObject.clone();
fuente
Si. Necesita copiar en profundidad su objeto.
fuente
Esto tambien funciona. Asumiendo modelo
Primero agregue
compile 'com.google.code.gson:gson:2.8.1'
a su aplicación> gradle & sync. EntoncesPuede excluir el uso de un campo utilizando la
transient
palabra clave después del modificador de acceso.Nota: esta es una mala práctica. Tampoco recomiendo usar
Cloneable
oJavaSerialization
es lento y roto. Escriba el constructor de copias para obtener el mejor rendimiento ref .Algo como
Estadísticas de prueba de iteración 90000: la
línea
UserAccount clone = gson.fromJson(gson.toJson(aO), UserAccount.class);
tarda 808 msLa línea
UserAccount clone = new UserAccount(aO);
tarda menos de 1 msConclusión: usa gson si tu jefe está loco y prefieres la velocidad. Use el segundo constructor de copias si prefiere la calidad.
También puede usar el complemento generador de código de constructor de copia en Android Studio.
fuente
Aquí hay una explicación decente de
clone()
si terminas necesitándolo ...Aquí: clonar (método Java)
fuente
Use una utilidad de clonación profunda:
Esto copiará en profundidad cualquier objeto Java, échale un vistazo en https://github.com/kostaskougios/cloning
fuente
Deep Cloning es su respuesta, que requiere implementar la
Cloneable
interfaz y anular elclone()
método.Lo llamarás así
DummyBean dumtwo = dum.clone();
fuente
dummy
, aString
, es inmutable, no necesita copiarloPara hacer eso tienes que clonar el objeto de alguna manera. Aunque Java tiene un mecanismo de clonación, no lo use si no es necesario. Cree un método de copia que haga la copia por usted y luego haga:
Aquí hay más consejos sobre diferentes técnicas para realizar una copia.
fuente
Además de copiar explícitamente, otro enfoque es hacer que el objeto sea inmutable (ningún
set
método mutante u otro). De esta manera, la pregunta nunca surge. La inmutabilidad se vuelve más difícil con objetos más grandes, pero ese otro lado de eso es que te empuja en la dirección de dividirte en pequeños objetos coherentes y compuestos.fuente
Alternativa al método de copia del constructor de egaga . Probablemente ya tenga un POJO, así que simplemente agregue otro método
copy()
que devuelva una copia del objeto inicializado.Si ya tiene una
DummyBean
y quiere una copia:Pero ambos funcionan bien, en última instancia depende de usted ...
fuente
fuente
Puede copiar en profundidad automáticamente con XStream, desde http://x-stream.github.io/ :
Agréguelo a su proyecto (si usa maven)
Entonces
Con esto, tiene una copia sin la necesidad de implementar ninguna interfaz de clonación.
fuente
java.beans.XMLEncoder
una API Java estándar que también serialice a XML (aunque no precisamente para propósitos de copia profunda).y en tu código:
fuente
Pase el objeto que desea copiar y obtenga el objeto que desea:
Ahora analiza el
objDest
objeto deseado.¡Feliz codificación!
fuente
Puede intentar implementar
Cloneable
y usar elclone()
método; sin embargo, si usa el método de clonación, debería, por norma, SIEMPRE anularObject
elpublic Object clone()
método.fuente
Si puede agregar una anotación al archivo fuente, se puede usar un procesador de anotación o un generador de código como este .
Se
DummyBeanBuilders
generará una clase , que tiene un método estáticodummyBeanUpdater
para crear copias superficiales, de la misma manera que lo haría manualmente.fuente
Úselo
gson
para duplicar un objeto.Supongamos que tengo un objeto
person
.fuente