Ferramentas de Usuário

Ferramentas de Site


dev_geral:java:tutorial:0510_especialmetodosobject

Métodos da Classe Object

A classe Object contém alguns objectos que todas as sub-classes devem redefinir, isto é, todas as classes que implementarmos devem redefinir estes métodos de modo a garantir um funcionamento adequado em toda a plataforma Java.

Nem todos estes métodos são necessários, e a classe Object oferece implementações que são usadas quando as sub-classes não fornecem uma implementação própria, mas é conveniente que estejam implementados dado que alguns métodos e classes que existem na plataforma esperam que cada nova classe re-implemente estes métodos (ex: as classes do package java.util.collections, que fornecem estruturas de dados, esperam que os métodos equals e hashCode sejam redefinidos).

Método: clone

Permite criar e devolver uma cópia do objecto. Para que este método possa ser usado, as classes precisam implementar a interface Cloneable. Por omissão este método devolve uma cópia da referência do objecto, efectuando um shallow copy1)

Por omissão, o método clone da classe Object tem apenas:

public Object clone() {
    return this;
}

Como vemos, devolve apenas a referência para o objecto, o que não significa uma cópia real. Para que a cópia passe a ser correcta teremos de implementar o método clone e a interface Cloneable nas nossas classes.

public class Ponto implements Cloneable {
    private int x;
    private int y;
 
    public Ponto() {
        this(0,0);
    }
 
    public Ponto(int x, int y) {
        this.x = x;
        this.y = y;
    }
 
    //criando um novo objecto usando o construtor para definir os valores
    public Ponto clone() {
        return new Ponto(x, y);
    }
 
    //ou definir os valores depois de usar o construtor e devolver a referência
    //util quando se pretende fazer outras operações
    public Ponto clone() {
       Ponto p = new Ponto();
       p.x = this.x;
       p.y = this.y;
 
       return p;
    }
}

Método: equals

Indica se o objecto passado por parâmetro é igual ao objecto usado para invocar o método. Por omissão, o método equals compara apenas referências, e desta forma, dado que duas referências só são iguais se apontarem para o mesmo objecto, o método equals da classe Object apenas devolve verdadeiro se compararmos um objecto com ele próprio.

A implementação existem na classe Object é2):

public boolean equals(Object obj) {
    return this == obj;
}

Como vimos esta implementação não nos serve de muito, uma implementação mais útil seria:

public class Ponto {
    private int x;
    private int y;
 
    public Ponto(int x, int y) {
        this.x = x;
        this.y = y;
    }
 
    public boolean equals(Object obj) {
        //se é o próprio ponto então são iguais
        if(this == obj) {
            return true;
        }
 
        //se não é instância da classe Ponto, nunca podem ser iguais
        if(!(obj instanceof Ponto)) {
            return false;
        }
 
        //Se não é o próprio ponto mas é uma instância de ponto
        //então vamos comparar os valores para ver se são iguais
        Ponto outro = (Ponto)obj;
 
        return this.x = outro.x && this.y = outros.y;
        }
}    

Existem vários exemplos onde, em vez do operador instanceof se usa o método getClass para a comparação. As diferenças dependem do objectivo e são negligenciáveis. O resultado é o mesmo: confirmar que o objecto passado pode ser convertido para a classe e comparado.

Método: finalize

O método finalize permite executar algum código especial antes do objecto ser removido pelo Garbage Collector. O Garbage Collector, a quando da remoção de objectos que não estão mais referenciados, executa o método finalize dos objectos na primeira fase de remoção.

Neste método é possível colocar código que permita remover outros recursos juntamente com este objecto. No entanto, este é um método que não deve ser usado indiscriminadamente para libertar recursos, o programador deve ter o cuidado de estrutura o seu código de modo a não precisar de usar o método finalize.

Método: hashCode

Este método deve ser re-implementado sempre que se re-implemente o método equals e sempre que se usem estruturas de dados hashtable, sejam a class HashTable, HashMap ou qualquer uma das várias implementações derivadas. Nestas estruturas, o valor devolvido pelo método hasCode é usado como índice.

O método hashCode deve devolver um inteiro que permita verificar se dois objectos são iguais ou diferentes, é um complemento ao método equals. Por omissão, a implementação deste método na classe Object apenas compara a referência, e não os valores, mas deve ser implementado de modo a que os valores dos objectos sejam comparados para que possamos garantir que, quando o método equals devolve verdadeiro para dois objectos, o método hashCode devolve um inteiro igual nos dois objectos.

Uma implementação típica, considerando como exemplo a classe seguinte:

public class Pessoa() {
 
    private nome;
 
    //...
 
    public boolean equals(Object obj) {
        //...
    }
 
    @Override
    public int hashCode() {
        //User dois inteiros aleatórios, 
        //preferencialmente números primos
        int hash = 7;
        hash = 13 * hash + (this.nome != null ? this.nome.hashCode() : 0);
        return hash;
    }
}

Método: toString

O método toString devolve uma String que represente este objecto. O valor devolvido pode ser qualquer coisa mas é tipicamente organizado de modo a devolver uma representação que facilite a nossa leitura, por exemplo, uma classe que represente um ponto poderá devolver as coordenadas sob a forma (x, y), uma classe que represente uma pessoa poderá devolver o nome, etc.

Se não for re-implementado, este método devolve apenas uma hash que representa o endereço de memória que o objecto ocupa.

Exemplo:

public class Ponto {
    private int x;
    private int y;
 
    public Ponto(int x, int y) {
        this.x = x;
        this.y = y;
    }
 
    public String toString() {
        return "("+ x + ", "+ y + ")";
    }
}

Navegação

1)
Uma shallow copy é o processo pelo qual apenas as referências são copias, ficamos assim com duas referências que apontam para o mesmo objecto e não com dois objectos iguais.
2)
Rever o operador ==.
dev_geral/java/tutorial/0510_especialmetodosobject.txt · Última modificação em: 2018/05/14 21:37 (edição externa)