Conclusões
Tendo dissecado os quatro exemplos arbitrariamente escolhidos de implementações de igual a (), o que concluímos?
Primeiro de tudo: existem duas maneiras substancialmente diferentes de executar a verificação de correspondência de tipo em uma implementação de igual a (). Uma classe pode permitir a comparação de tipos mistos entre objetos de super e subclasse por meio do operador instanceof, ou uma classe pode tratar objetos de tipos diferentes como diferentes por meio do teste getClass (). Os exemplos acima ilustraram muito bem que implementações de equals () usando getClass () são geralmente mais robustas do que aquelas implementações usando instanceof.
A instância do teste está correta apenas para as classes finais ou se pelo menos o método equals () for final em uma superclasse. O último implica essencialmente que nenhuma subclasse deve estender o estado da superclasse, mas só pode adicionar funcionalidades ou campos irrelevantes para o estado e o comportamento do objeto, como campos transitórios ou estáticos.
As implementações usando o teste getClass (), por outro lado, sempre cumprem o contrato equals (); eles estão corretos e robustos. Eles são, no entanto, semanticamente muito diferentes das implementações que usam a instância do teste. Implementações usando getClass () não permitem a comparação de objetos de subclasse com superclasse, nem mesmo quando a subclasse não adiciona nenhum campo e nem deseja substituir igual a (). Uma extensão de classe "trivial", por exemplo, seria a adição de um método de depuração-impressão em uma subclasse definida exatamente para esse propósito "trivial". Se a superclasse proibir a comparação de tipos mistos por meio da verificação getClass (), a extensão trivial não seria comparável à sua superclasse. Se isso é ou não um problema, depende totalmente da semântica da classe e do objetivo da extensão.
x instanceof SomeClass
é falsa sex
fornull
. Portanto, a segunda sintaxe não precisa da verificação nula.