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).
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; } }
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.
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.
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; } }
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 + ")"; } }
<< Packages :: Início :: Redefinição de Métodos >>