Construtor Java Copy
1. Introdução
Um construtor de cópia em uma classe Java é umconstructor quecreates an object using another object of the same Java class.
Isso é útil quando queremos copiar um objeto complexo que tem vários campos, ou quando queremos fazer umdeep copy de um objeto existente.
2. Como criar um construtor de cópias
Para criar um construtor de cópia, primeiro podemos declarar um construtor que aceita um objeto do mesmo tipo que um parâmetro:
public class Employee {
private int id;
private String name;
public Employee(Employee employee) {
}
}
Em seguida, copiamos cada campo do objeto de entrada para a nova instância:
public class Employee {
private int id;
private String name;
public Employee(Employee employee) {
this.id = employee.id;
this.name = employee.name;
}
}
O que temos aqui é umshallow copy, o que é bom, pois todos os nossos campos - uminte umString neste caso - sãoprimitive types ouimmutable types.
Se a classe Java tiver campos mutáveis, podemos fazer umdeep copy dentro de seu construtor de cópia. Com uma cópia detalhada, o objeto recém-criado é independente do original porque criamos uma cópia distinta de cada objeto mutável:
public class Employee {
private int id;
private String name;
private Date startDate;
public Employee(Employee employee) {
this.id = employee.id;
this.name = employee.name;
this.startDate = new Date(employee.startDate.getTime());
}
}
3. Copiar Construtor vs. Clone
Em Java, também podemos usar o métodoclone para criar um objeto a partir de um objeto existente. No entanto, o construtor de cópia tem algumas vantagens sobre o métodoclone:
-
O construtor de cópias é muito mais fácil de implementar. Não precisamos implementar a interfaceCloneablee manipularCloneNotSupportedException.
-
O métodoclone retorna uma referênciaObject geral. Portanto, precisamos convertê-lo no tipo apropriado.
-
Não podemos atribuir um valor a um campofinal no métodoclone. No entanto, podemos fazer isso no construtor de cópias.
4. Problemas de herança
Os construtores de cópia em Java não são herdáveis por subclasses. Portanto, se tentarmos inicializar um objeto filho de uma referência de classe pai,we will face a casting issue ao cloná-lo com o construtor de cópia.
Para ilustrar esse problema, vamos primeiro criar uma subclasse deEmployee e seu construtor de cópia:
public class Manager extends Employee {
private List directReports;
// ... other constructors
public Manager(Manager manager) {
super(manager.id, manager.name, manager.startDate);
this.directReports = directReports.stream()
.collect(Collectors.toList());
}
}
Em seguida, declaramos uma variávelEmployee e a instanciamos com o construtorManager:
Employee source = new Manager(1, "example Manager", startDate, directReports);
Como o tipo de referência éEmployee, temos que convertê-lo para o tipoManager para que possamos usar o construtor de cópia da classeManager:
Employee clone = new Manager((Manager) source);
Podemos obterClassCastException em tempo de execução se o objeto de entrada não for uma instância da classeManager.
Uma maneira de evitar a conversão no construtor de cópia é criar um novo método herdável para ambas as classes:
public class Employee {
public Employee copy() {
return new Employee(this);
}
}
public class Manager extends Employee {
@Override
public Employee copy() {
return new Manager(this);
}
}
Em cada método de classe, chamamos seu construtor de cópia com a entrada do objetothis. Dessa maneira, podemos garantir que o objeto gerado seja igual ao objeto chamador:
Employee clone = source.copy();
5. Conclusão
Neste tutorial, mostramos como criar um construtor de cópias com alguns exemplos de código. Além disso, discutimos vários motivos pelos quais devemos evitar o métodoclone.
O construtor Copy tem um problema de conversão quando o usamos para clonar um objeto de classe filho cujo tipo de referência é a classe pai. Fornecemos uma solução para esse problema.
Como sempre, o código-fonte do tutorial está disponívelover on GitHub.