Atualizado: 16/08/2025

Este conteúdo é original e não foi gerado por inteligência artificial.

Tipos por referência e cópia de objetos em Java

Em Java, todas as instâncias de classes são tipos por referência. Isso significa que uma variável de referência não armazena diretamente o objeto, mas sim um endereço de memória que aponta para ele. Esse comportamento é fundamental para entender como os objetos se comportam ao serem atribuídos a outras variáveis.

Considere o exemplo:

public class Program {
    public static void main(String[] args) {
        Person tom = new Person("Tom", 23);
        tom.display();      // Person Tom

        Person bob = tom;
        bob.setName("Bob");

        tom.display();      // Person Bob
    }
}

class Person {
    private String name;
    private int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    void setName(String name) {
        this.name = name;
    }
    void setAge(int age) {
        this.age = age;
    }
    void display() {
        System.out.printf("Person Name: %s \n", name);
    }
}

Nesse código, bob e tom acabam apontando para o mesmo objeto na memória. Alterar o nome usando bob.setName("Bob") também altera o valor visualizado por tom.


Clonando objetos para evitar referências compartilhadas

Para criar um novo objeto com os mesmos valores, é necessário clonar a instância original. O Java fornece suporte para isso por meio do método clone() e da interface Cloneable.

class Person implements Cloneable {
    private String name;
    private int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    void setName(String name) {
        this.name = name;
    }
    void setAge(int age) {
        this.age = age;
    }
    void display() {
        System.out.printf("Person %s \n", name);
    }

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

A interface Cloneable indica que a classe permite clonagem. O método clone() chama super.clone() (implementação padrão de Object), que cria uma cópia superficial do objeto.

Uso:

try {
    Person tom = new Person("Tom", 23);
    Person bob = tom.clone();
    bob.setName("Bob");

    tom.display();      // Person Tom
} catch (CloneNotSupportedException ex) {
    System.out.println("Cloneable not implemented");
}

Cópia superficial e seus limites

A cópia superficial (shallow copy) copia apenas os valores dos campos primitivos e as referências para objetos internos. Isso significa que objetos aninhados continuam sendo compartilhados entre o original e o clone.

Exemplo:

class Book implements Cloneable {
    private String name;
    private Author author;

    public void setName(String n) { name = n; }
    public String getName() { return name; }

    public void setAuthor(String n) { author.setName(n); }
    public String getAuthor() { return author.getName(); }

    Book(String name, String author) {
        this.name = name;
        this.author = new Author(author);
    }

    public String toString() {
        return "Livro '" + name + "' (autor " + author + ")";
    }

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

class Author {
    private String name;

    public void setName(String n) { name = n; }
    public String getName() { return name; }

    public Author(String name) {
        this.name = name;
    }
}

Se clonarmos e alterarmos o autor no clone, o livro original também será afetado:

try {
    Book book = new Book("War and Peace", "Leo Tolstoy");
    Book book2 = book.clone();
    book2.setAuthor("Ivan Turgenev");

    System.out.println(book.getAuthor()); // Ivan Turgenev
} catch (CloneNotSupportedException ex) {
    System.out.println("Cloneable not implemented");
}

Isso ocorre porque o campo author é apenas uma referência compartilhada.


Cópia profunda para independência total

Para evitar esse problema, é necessário implementar uma cópia profunda (deep copy), criando novas instâncias para os objetos internos.

O primeiro passo é tornar Author também clonável:

class Author implements Cloneable {
    private String name;

    public void setName(String n) { name = n; }
    public String getName() { return name; }

    public Author(String name) {
        this.name = name;
    }

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

Agora, modificamos o método clone() de Book para clonar também o autor:

public Book clone() throws CloneNotSupportedException {
    Book newBook = (Book) super.clone();
    newBook.author = (Author) author.clone();
    return newBook;
}

Com essa alteração, book e book2 terão autores totalmente independentes, garantindo que mudanças em um não afetem o outro.


Resumo

  • Objetos em Java são armazenados como referências, e variáveis guardam o endereço de memória.
  • Ao atribuir uma variável de referência a outra, ambas passam a apontar para o mesmo objeto.
  • O método clone() cria uma nova instância copiando os valores do objeto original.
  • A cópia superficial (shallow copy) copia apenas referências internas, fazendo com que objetos internos sejam compartilhados.
  • A cópia profunda (deep copy) cria novas instâncias para todos os objetos internos, garantindo independência total.
Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com