valores pasar otro objeto datos copiar clonar atributos java object copy clone

pasar - ¿Cómo copio un objeto en Java?



copiar valores de un objeto a otro java (21)

¿Por qué no hay respuesta para usar la API de Reflection?

private static Object cloneObject(Object obj){ try{ Object clone = obj.getClass().newInstance(); for (Field field : obj.getClass().getDeclaredFields()) { field.setAccessible(true); field.set(clone, field.get(obj)); } return clone; }catch(Exception e){ return null; } }

Es realmente simple

EDITAR: Incluir objeto hijo a través de recursión

private static Object cloneObject(Object obj){ try{ Object clone = obj.getClass().newInstance(); for (Field field : obj.getClass().getDeclaredFields()) { field.setAccessible(true); if(field.get(obj) == null || Modifier.isFinal(field.getModifiers())){ continue; } if(field.getType().isPrimitive() || field.getType().equals(String.class) || field.getType().getSuperclass().equals(Number.class) || field.getType().equals(Boolean.class)){ field.set(clone, field.get(obj)); }else{ Object childObj = field.get(obj); if(childObj == obj){ field.set(clone, clone); }else{ field.set(clone, cloneObject(field.get(obj))); } } } return clone; }catch(Exception e){ return null; } }

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 a dumtwo y cambiar dum sin afectar al dumtwo . Pero el código anterior no está haciendo eso. Cuando cambio algo en dum , el mismo cambio está sucediendo en dumtwo también.

Supongo que cuando digo dumtwo = dum , Java solo copia la referencia . Entonces, ¿hay alguna manera de crear una copia nueva de dum y asignársela a dumtwo ?


Agregue Cloneable código Cloneable y debajo de su clase

public Object clone() throws CloneNotSupportedException { return super.clone(); }

Utilice este clonedObject = (YourClass) yourClassObject.clone();


Aparte de la copia explícita, otro enfoque es hacer que el objeto sea inmutable (sin set u otros métodos de mutación). De esta manera nunca surge la pregunta. La inmutabilidad se vuelve más difícil con los objetos más grandes, pero ese otro lado es que te empuja en la dirección de la división en pequeños objetos y compuestos coherentes.



Crear un constructor de copia:

class DummyBean { private String dummy; public DummyBean(DummyBean another) { this.dummy = another.dummy; // you can access } }

Cada objeto tiene también un método de clonación que se puede usar para copiar el objeto, pero no lo use. Es demasiado fácil crear una clase y hacer un método de clonación incorrecto. Si vas a hacer eso, lee al menos lo que Joshua Bloch tiene que decir al respecto en Effective Java .


Deep Cloning es su respuesta, que requiere implementar la interfaz Cloneable y reemplazar el método clone() .

public class DummyBean implements Cloneable { private String dummy; public void setDummy(String dummy) { this.dummy = dummy; } public String getDummy() { return dummy; } @Override public Object clone() throws CloneNotSupportedException { DummyBean cloned = (DummyBean)super.clone(); cloned.setDummy(cloned.getDummy()); // the above is applicable in case of primitive member types, // however, in case of non primitive types // cloned.setNonPrimitiveType(cloned.getNonPrimitiveType().clone()); return cloned; } }

Lo llamará así DummyBean dumtwo = dum.clone();


En el paquete import org.apache.commons.lang.SerializationUtils; hay un metodo

SerializationUtils.clone(Object);

Ejemplo:

this.myObjectCloned = SerializationUtils.clone(this.object);


Esto funciona tambien Asumiendo modelo

class UserAccount{ public int id; public String name; }

Primero agregue compile ''com.google.code.gson:gson:2.8.1'' a su aplicación> gradle & sync. Entonces

Gson gson = new Gson(); updateUser = gson.fromJson(gson.toJson(mUser),UserAccount.class);

Puede excluir el uso de un campo utilizando transient palabra clave transient después del modificador de acceso.

Nota: Esta es una mala práctica. Tampoco recomiendo usar Cloneable o JavaSerialization Es lento y está roto. Escribir copia de constructor para el mejor rendimiento ref .

Algo como

class UserAccount{ public int id; public String name; //empty constructor public UserAccount(){} //parameterize constructor public UserAccount(int id, String name) { this.id = id; this.name = name; } //copy constructor public UserAccount(UserAccount in){ this(in.id,in.name); } }

Estadísticas de prueba de 90000 iteración:
Línea UserAccount clone = gson.fromJson(gson.toJson(aO), UserAccount.class); toma 808ms

Línea UserAccount clone = new UserAccount(aO); toma menos de 1 ms

Conclusión: usa gson si tu jefe está loco y prefieres la velocidad. Usa el segundo constructor de copias si prefieres calidad.

También puede usar el complemento generador de código de constructor de copia en Android Studio.


Para hacer eso tienes que clonar el objeto de alguna manera. Aunque Java tiene un mecanismo de clonación, no lo use si no tiene que hacerlo. Cree un método de copia que haga el trabajo de copia por usted, y luego haga:

dumtwo = dum.copy();

Here hay algunos consejos más sobre diferentes técnicas para lograr una copia.


Pase el objeto que desea copiar y obtenga el objeto que desea:

private Object copyObject(Object objSource) { try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(objSource); oos.flush(); oos.close(); bos.close(); byte[] byteData = bos.toByteArray(); ByteArrayInputStream bais = new ByteArrayInputStream(byteData); try { objDest = new ObjectInputStream(bais).readObject(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } return objDest; }

Ahora analiza el objDest en el objeto deseado.

¡Feliz codificación!


Puede realizar copias en profundidad automáticamente con XStream, desde http://x-stream.github.io/ :

XStream es una biblioteca simple para serializar objetos a XML y viceversa.

Agrégalo a tu proyecto (si usas maven)

<dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.3.1</version> </dependency>

Entonces

DummyBean dum = new DummyBean(); dum.setDummy("foo"); DummyBean dumCopy = (DummyBean) XSTREAM.fromXML(XSTREAM.toXML(dum));

Con esto tienes una copia sin la necesidad de implementar ninguna interfaz de clonación.


Puedes intentar implementar Cloneable y usar el método clone() ; sin embargo, si usa el método de clonación, debería, por norma general, SIEMPRE anular el método public Object clone() .


Sí, solo estás haciendo una referencia al objeto. Puede clonar el objeto si implementa Cloneable .

Echa un vistazo a este artículo wiki sobre la copia de objetos.

Consulte aquí: copia de objetos



Si puede agregar una anotación al archivo de origen, se puede usar un procesador de anotaciones o un generador de código como este .

import net.zerobuilder.BeanBuilder @BeanBuilder public class DummyBean { // bean stuff }

Se DummyBeanBuilders una clase DummyBeanBuilders , que tiene un método estático dummyBeanUpdater para crear copias poco profundas, de la misma manera que lo haría manualmente.

DummyBean bean = new DummyBean(); // Call some setters ... // Now make a copy DummyBean copy = DummyBeanBuilders.dummyBeanUpdater(bean).done();


Solo sigue como sigue:

public class Deletable implements Cloneable{ private String str; public Deletable(){ } public void setStr(String str){ this.str = str; } public void display(){ System.out.println("The String is "+str); } protected Object clone() throws CloneNotSupportedException { return super.clone(); } }

y donde quiera que desee obtener otro objeto, simplemente realice la clonación. p.ej:

Deletable del = new Deletable(); Deletable delTemp = (Deletable ) del.clone(); // this line will return you an independent // object, the changes made to this object will // not be reflected to other object


Utilice una utilidad de clonación profunda:

SomeObjectType copy = new Cloner().deepClone(someObject);

Esto hará una copia profunda de cualquier objeto java, échale un vistazo en https://github.com/kostaskougios/cloning


Utilizo la biblioteca JSON de Google para serializarla y luego crear una nueva instancia del objeto serializado. Hace copia profunda con algunas restricciones:

  • no puede haber referencias recursivas

  • no copiará matrices de tipos dispares

  • Las matrices y listas deben escribirse o no encontrará la clase para crear instancias.

  • Es posible que necesite encapsular cadenas en una clase que se declara a sí mismo

También utilizo esta clase para guardar las preferencias del usuario, las ventanas y otras cosas para volver a cargar en el tiempo de ejecución. Es muy fácil de usar y eficaz.

import com.google.gson.*; public class SerialUtils { //___________________________________________________________________________________ public static String serializeObject(Object o) { Gson gson = new Gson(); String serializedObject = gson.toJson(o); return serializedObject; } //___________________________________________________________________________________ public static Object unserializeObject(String s, Object o){ Gson gson = new Gson(); Object object = gson.fromJson(s, o.getClass()); return object; } //___________________________________________________________________________________ public static Object cloneObject(Object o){ String s = serializeObject(o); Object object = unserializeObject(s,o); return object; } }


Básico: Copia de objetos en Java.

Supongamos un objeto- obj1 , que contiene dos objetos, contenidaObj1 y contenidaObj2 .

Copia superficial:
la copia superficial crea una nueva instance de la misma clase y copia todos los campos a la nueva instancia y la devuelve. La clase de objeto proporciona un método de clone y proporciona soporte para la copia superficial.

Copia profunda:
Una copia profunda se produce cuando un objeto se copia junto con los objetos a los que se refiere . La imagen de abajo muestra obj1 después de realizar una copia profunda en él. No solo se ha copiado obj1 , sino que también se han copiado los objetos que contiene. Podemos usar Java 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 Copia defensiva , constructores de copia (como respuesta @egaga) o métodos de fábrica estáticos .

  1. Si tiene un objeto, sabe que tiene un método público clone() , pero no sabe el tipo del objeto en el momento de la compilación, entonces tiene un problema. Java tiene una interfaz llamada Cloneable . En la práctica, deberíamos implementar esta interfaz si queremos hacer un objeto Cloneable . Object.clone está protegido , por lo que debemos anularlo con un método público para que sea accesible.
  2. Otro problema surge cuando intentamos copiar en profundidad un objeto complejo . Supongamos que el método clone() de todas las variables de objeto miembro también hace una copia profunda, esto es demasiado arriesgado como una suposición. Debes controlar el código en todas las clases.

Por ejemplo, org.apache.commons.lang.SerializationUtils tendrá un método para la clonación profunda utilizando la serialización ( Source ). Si necesitamos clonar Bean, hay un par de métodos de utilidad en org.apache.commons.beanutils ( Source ).

  • cloneBean un bean en función de los captadores y establecedores de propiedades disponibles, incluso si la propia clase de bean no implementa Cloneable.
  • copyProperties los valores de propiedad del bean de origen en el bean de destino para todos los casos en los que los nombres de propiedad sean los mismos.

class DB { private String dummy; public DB(DB one) { this.dummy = one.dummy; } }


public class MyClass implements Cloneable { private boolean myField= false; // and other fields or objects public MyClass (){} @Override public MyClass clone() throws CloneNotSupportedException { try { MyClass clonedMyClass = (MyClass)super.clone(); // if you have custom object, then you need create a new one in here return clonedMyClass ; } catch (CloneNotSupportedException e) { e.printStackTrace(); return new MyClass(); } } }

y en su código:

MyClass myClass = new MyClass(); // do some work with this object MyClass clonedMyClass = myClass.clone();