De forma geral quando falamos em clonagem, estamos querendo dizer que estamos querendo obter uma cópia do objeto original. A classe Object possui um método denominado .clone() que cria e retorna uma cópia do objeto em questão.
O que vamos ver aqui é que o que se quer dizer como cópia não é necessariamente o que poderíamos esperar. Para que este método funcione, é necessário que o objeto implemente a interface Cloneable. Se ele não implementar é gerada uma exceção CloneNotSupportedException. Todos os arrays implementam esta interface.
Esse método cria uma nova instância do objeto e inicializa todos os campos com o mesmo conteúdo dos respectivos campos. Os conteúdos dos campos não são clonados. A documentação do Java caracteriza esta cópia como sendo "shallow copy". Não é uma "deep copy". Com isto queremos dizer que se a classe contem somente campos primitivos ou referência para objetos imutáveis, o objeto clonado será completamente clonado.
Como assim?
Exemplo 1)
Class Classe1 implements Cloneable {
String nome;
int inteiro;
boolean boleano;
}
public Class
Classe1 c1 = new Classe1();
c1.nome = "nome original";
c1.inteiro = 1;
c2.booleano = true;
Classe1 c2 = c1.clone();
c2.inteiro = 2;
System.out
Campos mutáveis (como classes internas) que estão dentro da estrutura ("deep") do objeto ao serem clonados, não são criados novos objetos, somente é copiada a referência, portanto podemos ter comportamento que podem parecer inesperados como no exemplo abaixo:
Exemplo 2)
Class Campo {
String campo1;
boolean campo2;
}
class Classe2 implements Cloneable {
String nome;
int inteiro;
boolean boleano;
Campo campo;
}
Classe2 c1 = new Classe1();
Classe2 c2 = c1.clone();
c1.campo.campo1 = "novo valor"
Para resolver isto temos que tratar estes objetos, criando clones deles também.
Vamos ver um exemplo, primeiro fazendo tudo certo, isto é, implementando "deep cloning" - copiando os atributos e os objetos encapsulados. Cada exemplo tem duas classes: uma funcionario que será clonada e outra que gera o exemplo.
Criei um objeto func1, clone este objeto para func2. Alterei os campos e consigo ver que os dois são independentes. A saída de Exemplo é:
Vamos ver agora uma implementação onde não foi clonado o objeto interno explicitamente.
Vamos ver o que acontece se tento alterar o endereço de fun2. Veja o resultado da cidade para func1 e func2:
Alterei func2 e o resultado apareceu em func1. Por quê?
Porque como o objeto interno não é clonado, somente a referência do objeto é clonada, o que significa que o objeto endereco de func1 e func2 são os mesmos. Uma alteração em um reflete no outro.
Nenhum comentário:
Postar um comentário