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 + ")";
}
}
-
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. ↩
-
Rever o operador ==. ↩