¿Alguna razón para preferir getClass() sobre instanciade al generar .equals()?

Resuelto Kip asked hace 15 años • 11 respuestas

Estoy usando Eclipse para generar .equals()y .hashCode(), y hay una opción denominada "Usar 'instancia de' para comparar tipos". El valor predeterminado es que esta opción no esté marcada y se use .getClass()para comparar tipos. ¿Hay alguna razón por la que debería .getClass()preferirlo instanceof?

Sin uso instanceof:

if (obj == null)
  return false;
if (getClass() != obj.getClass())
  return false;

Usando instanceof:

if (obj == null)
  return false;
if (!(obj instanceof MyClass))
  return false;

Normalmente marco la instanceofopción y luego entro y elimino la if (obj == null)marca " ". (Es redundante ya que los objetos nulos siempre fallarán instanceof). ¿Hay alguna razón por la que sea una mala idea?

Kip avatar Feb 28 '09 03:02 Kip
Aceptado

Josh Bloch favorece su enfoque:

La razón por la que estoy a favor de este instanceofenfoque es que cuando lo usas getClass, tienes la restricción de que los objetos sólo son iguales a otros objetos de la misma clase, el mismo tipo de tiempo de ejecución. Si extiende una clase y le agrega un par de métodos inofensivos, luego verifica si algún objeto de la subclase es igual a un objeto de la superclase, incluso si los objetos son iguales en todos los aspectos importantes, obtendrá el sorprendente respuesta de que no son iguales. De hecho, esto viola una interpretación estricta del principio de sustitución de Liskov y puede conducir a un comportamiento muy sorprendente. En Java, es particularmente importante porque la mayoría de las colecciones ( HashTable, etc.) se basan en el método igual. Si coloca un miembro de la superclase en una tabla hash como clave y luego lo busca usando una instancia de subclase, no lo encontrará porque no son iguales.

Vea también esta respuesta SO .

El capítulo 3 de Java efectivo también cubre esto.

Michael Myers avatar Feb 27 '2009 20:02 Michael Myers

Si usa instanceof, realizar su equalsimplementación finalpreservará el contrato de simetría del método: x.equals(y) == y.equals(x). Si finalparece restrictivo, examine cuidadosamente su noción de equivalencia de objetos para asegurarse de que sus implementaciones primordiales mantengan completamente el contrato establecido por la Objectclase.


Lo que intento decir aquí es que si cree que getClass()es la única forma confiable de preservar la simetría, probablemente esté usando equals()el método incorrecto.

Claro, es fácil de usar getClass()para preservar la simetría requerida equals(), pero solo porque x.equals(y)y y.equals(x)siempre son falsos. La sustituibilidad de Liskov lo alentaría a encontrar una implementación que preserve la simetría y que pueda rendir truecuando tenga sentido. Si una subclase tiene una noción de igualdad radicalmente diferente, ¿es realmente una subclase?

erickson avatar Feb 27 '2009 21:02 erickson