W3docs

Classe Object do Java

Métodos herdados por todo objeto Java de java.lang.Object — toString, equals, hashCode, getClass, clone e finalize.

Toda classe em Java — quer você escreva extends Object ou não — está abaixo de java.lang.Object na hierarquia de tipos. Isso significa que toda referência que você possui tem um pequeno conjunto de métodos disponíveis: toString, equals, hashCode, getClass e alguns outros. Entender o que eles fazem por padrão e quando você deve substituí-los é a diferença entre objetos que funcionam bem com coleções, depuradores e frameworks — e objetos que não funcionam.

Este capítulo é o mapa do território. Os próximos capítulos detalham os métodos específicos (equals/hashCode, toString, clone) um de cada vez.

Extensão implícita

Escreva uma classe sem cláusula extends:

public class Box {
  int contents;
}

O compilador a trata como se você tivesse escrito public class Box extends Object. É por isso que você pode passar um Box para qualquer coisa declarada como Object — todo tipo de referência, em última análise, é um Object.

Os métodos herdados em resumo

MétodoO que o padrão faz
toString()Retorna ClassName@hashCodeHex — quase nunca é o que você quer
equals(Object)Igualdade por referência (==)
hashCode()Um valor derivado da identidade do objeto, não do seu conteúdo
getClass()O token Class<?> em tempo de execução — nunca nulo
clone()Uma cópia superficial campo a campo, mas somente em classes que implementam Cloneable; caso contrário, lança exceção
wait(), notify(), notifyAll()Primitivas de monitor de baixo nível usadas com synchronized
finalize()Hook chamado pelo GC antes de reclamar um objeto — obsoleto, não use

Os três primeiros — toString, equals e hashCode — são os que quase toda classe que carrega valores deve substituir, porque as versões herdadas descrevem a identidade de um objeto em vez de seu conteúdo. getClass você chama em objetos mas nunca substitui. As primitivas de threading você raramente usa diretamente. clone e finalize devem ser evitados em código moderno (clone tem seu próprio capítulo; finalize é substituído por try-with-resources e Cleaner).

Nota
Se você usa um record (Java 16+), o compilador gera toString, equals e hashCode para você a partir dos componentes — os três baseados no conteúdo, não na identidade. Isso elimina a maior parte do boilerplate deste capítulo. Veja Java Records.

toString — o padrão não é útil

O toString herdado retorna algo como Box@1540e19d. Esse é o nome da classe e o hash code de identidade em hexadecimal — inútil para logging, depuração ou qualquer tipo de diagnóstico:

Box b = new Box();
System.out.println(b);   // Box@1540e19d

Substitua-o para retornar algo legível — println, concatenação de string, frameworks de logging e depuradores de IDE chamam toString por você, então um bom método compensa em todo lugar:

@Override
public String toString() {
  return "Box[contents=" + contents + "]";
}

O próximo capítulo mostra como fazer isso corretamente.

equals e hashCode — andam juntos

O equals herdado só retorna true quando ambas as referências apontam para o mesmo objeto:

String a = new String("hi");
String b = new String("hi");
System.out.println(a == b);       // false — different objects
System.out.println(a.equals(b));  // true — String overrides equals

String substitui equals para comparar conteúdo. Uma classe que você escreve não faz isso, a menos que você substitua por conta própria. E no momento em que você substitui equals, também deve substituir hashCode — caso contrário, seus objetos se comportarão incorretamente em HashSet e HashMap. O capítulo sobre equals e hashCode cobre as regras exatas.

Aviso
Substituir equals sem substituir hashCode faz com que dois objetos que você considera iguais possam acabar em buckets de hash diferentes — então um HashSet armazena os dois sem problemas, e map.get(key) retorna null para uma chave que claramente está presente. Sempre substitua os dois juntos e mantenha-os consistentes: objetos iguais devem retornar hash codes iguais.

getClass — o token do tipo em tempo de execução

getClass() retorna o objeto Class<?> que descreve o tipo em tempo de execução:

Object o = "hello";
System.out.println(o.getClass().getName());  // java.lang.String

É usado em código reflexivo, por implementações de equals que desejam comparações de tipo exato e por saída de depuração. Note que getClass() é final — você não pode substituí-lo.

clone e Cloneable

Object.clone() é protected e só tem sucesso em classes que declaram explicitamente implements Cloneable. O resultado é uma cópia superficial: uma nova instância com os mesmos valores de campo, incluindo as mesmas referências a sub-objetos mutáveis. É uma API notoriamente desajeitada, coberta em detalhes no capítulo sobre clonagem.

wait / notify

Esses métodos, mais notifyAll, fazem parte das primitivas de concorrência de baixo nível originais do Java. Estão vinculados a blocos synchronized e são usados para construir padrões de espera por condição. Em código moderno, prefira os utilitários de nível mais alto em java.util.concurrent (locks, BlockingQueue, CompletableFuture); wait/notify brutos são raros fora de internos de bibliotecas.

finalize — deixe de lado

finalize() era a forma do GC dar ao seu objeto uma última chance de liberar recursos. Foi depreciado desde o Java 9 e removido em versões mais recentes. Use try-with-resources para I/O e java.lang.ref.Cleaner para o caso muito raro em que você precisa executar código após a coleta.

Um exemplo prático

java— editable, runs on the server

O que vem a seguir

A substituição mais comum — e mais propensa a erros — de um método de Object é equals combinado com hashCode. O próximo capítulo percorre o contrato que ambos os métodos devem honrar e os padrões para acertar. Continue para Java equals e hashCode.

Prática

Prática
O que o `toString()` padrão herdado de `Object` retorna?
O que o `toString()` padrão herdado de `Object` retorna?
Was this page helpful?