Igualdade, Hashing e Imutabilidade¶
Contratos de igualdade¶
Para referências não-nulas, equals deve ser reflexivo, simétrico, transitivo e
consistente, e deve retornar falso para null. Objetos iguais devem ter códigos hash
iguais durante uma execução.
Identidade (==) pergunta se referências denotam o mesmo objeto. Igualdade de valor
(equals) pergunta se objetos representam o mesmo valor sob seu contrato.
record BookId(String value) {
BookId {
Objects.requireNonNull(value, "value");
if (value.isBlank()) throw new IllegalArgumentException("blank id");
}
}
Um record deriva igualdade e hashing de seus componentes. O record é tão profundamente imutável quanto seus componentes; um componente que referencie uma lista mutável ainda exigirá cópia defensiva.
Projetando classes imutáveis¶
- tornar privado e final o estado que mantém os invariantes;
- validar construção;
- não expor estruturas internas mutáveis;
- copiar entradas e saídas mutáveis onde propriedade não é transferida;
- impedir a mutação por subclasses quando o contrato exigir.
Imutabilidade simplifica raciocínio, publicação segura, hashing e compartilhamento entre threads. Não torna automaticamente uma operação atômica sobre múltiplos valores imutáveis.
O guia prático expande essas regras para cópias rasas, vistas imutáveis, records, builders, snapshots e chaves de cache.
Consistência do comparador¶
Conjuntos e mapas ordenados usam a comparação para determinar a distinção entre chaves. Se um
comparador retornar zero para objetos que equals considera diferentes, a
coleção pode parecer "perder" uma chave. Ou torne a ordenação consistente com
igualdade ou documente a relação de equivalência alternativa.
Exercícios¶
- Explique por que a igualdade baseada em subclasses frequentemente quebra a simetria.
- Tornar uma classe contendo um
List<String>profundamente imutável. - Descrever a falha causada por mutar uma chave hash após inserção.