Pregunta

En java es un poco difícil de implementar una profunda objeto de la función de copia.Qué pasos tomar para asegurarse de que el objeto original y el clonado de una acción ninguna referencia?

¿Fue útil?

Solución

Una forma segura es serializar el objeto, entonces deserializar.Esto asegura que todo es una nueva marca de referencia.

He aquí un artículo acerca de cómo hacer esto de manera eficiente.

Advertencias:Es posible que las clases para anular la serialización de modo que las nuevas instancias no creado, por ejemplo,para los embarazos únicos.También por supuesto, esto no funciona si las clases no son Serializables.

Otros consejos

Algunas personas han mencionado que el uso o reemplazar Object.clone().Que no lo haga. Object.clone() tiene algunos de los principales problemas, y su uso se recomienda en la mayoría de los casos.Por favor, véase el Punto 11, de la "Efectivos De Java"por Joshua Bloch para obtener una respuesta completa.Yo creo que se puede utilizar de forma segura Object.clone() en un tipo primitivo de las matrices, pero aparte de que usted debe ser juicioso sobre el uso correcto y primordial clon.

Los esquemas que se basan en la serialización XML (o lo contrario) están desacoplados.

No hay respuesta fácil aquí.Si desea profundo copia de un objeto que se tiene que recorrer el objeto gráfico y copia a cada niño objeto de forma explícita a través del objeto del constructor de copia o estático de un método de fábrica que a su vez profundo copias el objeto secundario.Immutables (por ejemplo, Strings) no deben ser copiados.Como un aparte, deberá favorecer la inmutabilidad por esta razón.

Usted puede hacer una copia profunda con la serialización sin crear archivos.

Su objeto que desea copia profunda necesitará implement serializable.Si la clase no es la final o no puede ser modificada, extender la clase e implementar serializable.

Convertir la clase en una secuencia de bytes:

ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(object);
oos.flush();
oos.close();
bos.close();
byte[] byteData = bos.toByteArray();

Restaurar su clase a partir de una secuencia de bytes:

ByteArrayInputStream bais = new ByteArrayInputStream(byteData);
(Object) object = (Object) new ObjectInputStream(bais).readObject();

Usted puede hacer una serialización basado en la profunda clon usando org.apache.commons.lang3.SerializationUtils.clone(T) en Apache Commons Lang, pero tenga cuidado—el rendimiento es abismal.

En general, es la mejor práctica para escribir su propio clon métodos de cada clase de un objeto en el objeto gráfico de la necesidad de la clonación.

Una manera de implementar la copia profunda es agregar copia de constructores para cada clase asociada.Un constructor de copia se lleva a una instancia de 'este' como argumento único y copia todos los valores de se.Un poco de trabajo, pero bastante sencillo y seguro.

EDITAR:tenga en cuenta que usted no necesita utilizar métodos de descriptor de acceso para leer los campos.Usted puede acceder a todos los campos directamente porque la instancia de origen es siempre del mismo tipo de la instancia con el constructor de copia.Obvio, pero podría ser pasado por alto.

Ejemplo:

public class Order {

    private long number;

    public Order() {
    }

    /**
     * Copy constructor
     */
    public Order(Order source) {
        number = source.number;
    }
}


public class Customer {

    private String name;
    private List<Order> orders = new ArrayList<Order>();

    public Customer() {
    }

    /**
     * Copy constructor
     */
    public Customer(Customer source) {
        name = source.name;
        for (Order sourceOrder : source.orders) {
            orders.add(new Order(sourceOrder));
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Editar:Tenga en cuenta que cuando se utiliza la copia de constructores que usted necesita saber el tipo en tiempo de ejecución del objeto que se está copiando.Con el enfoque anterior, usted no puede copiar fácilmente una lista mezclada (usted podría ser capaz de hacer con un poco de código de reflexión).

Apache commons ofrece una forma rápida de profunda clonar un objeto.

My_Object object2= org.apache.commons.lang.SerializationUtils.clone(object1);

Usted puede el uso de una biblioteca que tiene una API sencilla, y se realiza relativamente rápido de la clonación con la reflexión (que debe ser más rápido que los métodos de serialización).

Cloner cloner = new Cloner();

MyClass clone = cloner.deepClone(o);
// clone is a deep-clone of o

XStream es muy útil en estos casos.Aquí es un simple código para hacer la clonación

private static final XStream XSTREAM = new XStream();
...

Object newObject = XSTREAM.fromXML(XSTREAM.toXML(obj));

Uno muy fácil y simple enfoque es el uso de Jackson JSON para serializar complejo de Objetos Java a JSON y la lectura.

http://wiki.fasterxml.com/JacksonInFiveMinutes

Uso XStream(http://x-stream.github.io/).Usted puede incluso controlar las propiedades que usted puede ignorar a través de anotaciones o especificar explícitamente el nombre de la propiedad a XStream clase.Por otra parte usted no necesita implementar clonable de la interfaz.

Para Framework Spring los usuarios.El uso de la clase org.springframework.util.SerializationUtils:

@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T object) {
     return (T) SerializationUtils.deserialize(SerializationUtils.serialize(object));
}

Profundo copiar sólo se puede hacer con cada clase del consentimiento.Si usted tiene control sobre la clase de jerarquía, a continuación, puede implementar el clonable interfaz y aplicar el método Clone.De lo contrario, hacer una copia profunda es imposible hacerlo de forma segura porque el objeto también puede ser compartido no de datos de recursos (por ejemplo,conexiones de base de datos).Sin embargo, en general profunda copia se considera de mala práctica en el entorno Java y deben ser evitados a través de un adecuado diseño de las prácticas.

import com.thoughtworks.xstream.XStream;

public class deepCopy {
    private static  XStream xstream = new XStream();

    //serialize with Xstream them deserialize ...
    public static Object deepCopy(Object obj){
        return xstream.fromXML(xstream.toXML(obj));
    }
}

Para objetos complicados y cuando el rendimiento no es significativa yo uso un json de la biblioteca, como gson para serializar el objeto json de texto, a continuación, deserializar el texto de obtener un nuevo objeto.

gson que basado en la reflexión se trabaja en la mayoría de los casos, salvo que transient los campos no serán copiados y objetos con referencia circular con causa StackOverflowError.

public static <T> T copy(T anObject, Class<T> classInfo) {
    Gson gson = new GsonBuilder().create();
    String text = gson.toJson(anObject);
    T newObject = gson.fromJson(text, classInfo);
    return newObject;
}
public static void main(String[] args) {
    String originalObject = "hello";
    String copiedObject = copy(originalObject, String.class);
}

He utilizado Dozer para la clonación de objetos java y es muy buena para eso , Kryo la biblioteca es otra gran alternativa.

1)

public static Object deepClone(Object object) {
   try {
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     ObjectOutputStream oos = new ObjectOutputStream(baos);
     oos.writeObject(object);
     ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
     ObjectInputStream ois = new ObjectInputStream(bais);
     return ois.readObject();
   }
   catch (Exception e) {
     e.printStackTrace();
     return null;
   }
 }

2)

    // (1) create a MyPerson object named Al
    MyAddress address = new MyAddress("Vishrantwadi ", "Pune", "India");
    MyPerson al = new MyPerson("Al", "Arun", address);

    // (2) make a deep clone of Al
    MyPerson neighbor = (MyPerson)deepClone(al);

Aquí su MyPerson y MyAddress clase debe implementar la interfaz serilazable

BeanUtils realmente hace un buen trabajo profundo de la clonación de frijoles.

BeanUtils.cloneBean(obj);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top