Introdução
Quando queremos copiar um objeto em Java, existem duas possibilidades que temos de considerar — uma cópia superficial e profundo de uma cópia.
a cópia superficial é a abordagem quando apenas copiamos os valores do campo e, portanto, a cópia pode depender do objeto original. Na abordagem de cópia profunda, certificamo-nos de que todos os objetos na árvore são copiados profundamente, para que a cópia não dependa de nenhum Objeto anterior existente que possa alguma vez mudar.,
neste artigo, vamos comparar estas duas abordagens e aprender quatro métodos para implementar a cópia profunda.
leitura adicional:
Construtor de cópias Java
copiar conjuntos em Java
Copiar um HashMap em Java
Maven Configuração
vamos usar três dependências Maven — Gson, Jackson e o Apache Commons Lang — testar diferentes maneiras de executar uma cópia de profundidade.
vamos adicionar estas dependências ao nosso pom.xml:
As últimas versões de Gson, Jackson e Apache Commons Lang podem ser encontradas em Maven Central.,
Modelo
A comparação de diferentes métodos para copiar objetos Java, vamos precisar de duas classes para trabalhar em:
class Address { private String street; private String city; private String country; // standard constructors, getters and setters}
class User { private String firstName; private String lastName; private Address address; // standard constructors, getters and setters}
Cópia Superficial
Uma cópia superficial é aquela em que nós só copiar os valores dos campos de um objeto para outro:
neste caso, pm != shallowCopy, o que significa que eles são objetos diferentes, mas o problema é que quando mudamos qualquer uma das propriedades do endereço original, isso também afetará o endereço do shallowCopy.,
não nos preocuparíamos com isso se o endereço fosse imutável, mas não é:
cópia profunda
uma cópia profunda é uma alternativa que resolve este problema. Sua vantagem é que pelo menos cada objeto mutável no grafo do objeto é copiado recursivamente.
Uma vez que a cópia não é dependente de qualquer objeto mutável que foi criado anteriormente, ela não será modificada por acidente, como vimos com a cópia rasa.
nas seguintes secções, mostraremos várias implementações de cópias profundas e demonstraremos esta vantagem.
5, 1., Construtor de cópia
A primeira implementação nós vamos implementar é baseado em construtores de cópia:
public Address(Address that) { this(that.getStreet(), that.getCity(), that.getCountry());}
public User(User that) { this(that.getFirstName(), that.getLastName(), new Address(that.getAddress()));}
Na implementação acima da cópia profunda, nós não criou novas Seqüências de caracteres em nosso construtor de cópia, porque String é uma classe imutável.como resultado, eles não podem ser modificados por acidente. Vejamos se isto funciona:
5.2. Interface clonável
a segunda implementação é baseada no método de clones herdado do objeto. Está protegido, mas temos de o anular como público.,
também vamos adicionar uma interface de marcação, Clonável, para as classes para indicar que as classes são realmente clonáveis.
Let’s add the clone() method to the Address class:
And now let’s implement clone() for the User class:
Note that the super.o clone () call devolve uma cópia rasa de um objecto, mas definimos cópias profundas de campos mutáveis manualmente, de modo que o resultado está correcto:
bibliotecas externas
os exemplos acima parecem fáceis, mas às vezes não se aplicam como solução quando não podemos adicionar um construtor adicional ou substituir o método de clone.,
isto pode acontecer quando nós não possuímos o código, ou quando o grafo de objeto é tão complicado que nós não terminaríamos o nosso projeto a tempo se nos focássemos em escrever Construtores adicionais ou implementar o método de clone em todas as classes do grafo de objeto.e depois? Neste caso, podemos usar uma biblioteca externa. Para obter uma cópia profunda, podemos serializar um objeto e, em seguida, desertificá-lo para um novo objeto.
vamos olhar para alguns exemplos.
6. 1., Apache Commons Lang
Apache Commons Lang has SerializationUtils#clone, which performs a deep copy when all classes in the object graph implement the Serializable interface.
Se o método encontrar uma classe que não é serializável, ele vai falhar e lançar uma série não controlada.
Por causa disso, precisamos adicionar a interface serializável para nossas classes:
6.2. A serialização de JSON com Gson
a outra maneira de serializar é usar a serialização de JSON. Gson é uma biblioteca que é usada para converter objetos em JSON e vice-versa.,
Ao contrário do Apache Commons Lang, GSON não precisa da interface serializável para fazer as conversões.
Let’s have a quick look at an example:
6.3. JSON Serialization With Jackson
Jackson is another library that supports JSON serialization. Esta implementação será muito semelhante à que usa o Gson, mas precisamos adicionar o construtor padrão para nossas classes.
vamos ver um exemplo:
conclusão
que implementação devemos usar ao fazer uma cópia profunda?, A decisão final muitas vezes dependerá das classes que copiaremos e se possuímos as classes no gráfico de objetos.
Como sempre, as amostras de código completas para este tutorial podem ser encontradas no GitHub.
Começar com Mola 5 e Primavera de Inicialização 2, através do Aprender a Primavera curso:
>> confira O CURSO