Estoy usando Eclipse para generar .equals()
y .hashCode()
, y hay una opción etiquetada "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 yo preferiría .getClass()
más instanceof
?
Sin usar instanceof
:
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Utilizando instanceof
:
if (obj == null)
return false;
if (!(obj instanceof MyClass))
return false;
Por lo general, verifico la instanceof
opción y luego entro y elimino el " if (obj == null)
" cheque. (Es redundante ya que los objetos nulos siempre fallarán instanceof
). ¿Hay alguna razón que sea una mala idea?
java
eclipse
equals
instanceof
Dormir
fuente
fuente
x instanceof SomeClass
es falsa six
esnull
. Por lo tanto, la segunda sintaxis no necesita la comprobación nula.Respuestas:
Si se utiliza
instanceof
, por lo que suequals
aplicaciónfinal
va a conservar el contrato de simetría del método:x.equals(y) == y.equals(x)
. Sifinal
parece restrictivo, examine cuidadosamente su noción de equivalencia de objetos para asegurarse de que sus implementaciones primordiales mantengan completamente el contrato establecido por laObject
clase.fuente
final
parece restrictivo" (en ambosequals
yhashCode
) luego usar lagetClass()
igualdad en lugar deinstanceof
para preservar los requisitos de simetría y transitividad delequals
contrato.Josh Bloch favorece su enfoque:
Vea también esta respuesta SO .
El eficaz capítulo 3 de Java también cubre esto.
fuente
getClass
no viola el LSP, ya que el LSP simplemente se relaciona con lo que se puede hacer con las instancias existentes, no con qué tipos de instancias se pueden construir. La clase devuelta porgetClass
es una propiedad inmutable de una instancia de objeto. El LSP no implica que deba ser posible crear una subclase donde esa propiedad indique cualquier clase que no sea la que la creó.Angelika Langers Secrets of equals se mete en eso con una discusión larga y detallada de algunos ejemplos comunes y conocidos, incluidos Josh Bloch y Barbara Liskov, descubriendo un par de problemas en la mayoría de ellos. Ella también se mete en el
instanceof
frentegetClass
. Alguna cita de ellafuente
La razón para usar
getClass
es garantizar la propiedad simétrica delequals
contrato. De igual a JavaDocs:Al usar instanceof, es posible no ser simétrico. Considere el ejemplo: Perro extiende Animal. Animal's
equals
hace uninstanceof
chequeo de Animal. El perroequals
hace uninstanceof
chequeo del perro. Dar Animal a y Perro d (con otros campos iguales):Esto viola la propiedad simétrica.
Para seguir estrictamente el contrato de igualdad, se debe garantizar la simetría y, por lo tanto, la clase debe ser la misma.
fuente
a.equals(c)
yb.equals(c)
, entoncesa.equals(b)
(el enfoque ingenuo de hacerDog.equals
soloreturn super.equals(object)
cuando!(object instanceof Dog)
pero verificando los campos adicionales cuando se trata de una instancia de Dog no violaría la simetría pero violaría la transitividad)getClass()
comprobación de igualdad, o puede utilizar unainstanceof
verificación si hacer susequals
yhashCode
métodosfinal
.Esto es algo de un debate religioso. Ambos enfoques tienen sus problemas.
Bloch tiene otro consejo relevante en Effective Java Second Edition :
fuente
getClass
violaría el LSP, a menos que la clase base documentara específicamente un medio por el cual debería ser posible hacer instancias de diferentes subclases que se comparen igual. ¿Qué violación de LSP ves?getClass()
no debe considerarse significativo más allá del hecho de que la clase en cuestión es convertible a la clase base, el rendimiento degetClass()
debe considerarse como cualquier otra propiedad que debe coincidir para que las instancias sean iguales.Corrígeme si estoy equivocado, pero getClass () será útil cuando quieras asegurarte de que tu instancia NO sea una subclase de la clase con la que estás comparando. Si usa instanceof en esa situación, NO puede saberlo porque:
fuente
Si desea asegurarse de que solo esa clase coincida, use
getClass() ==
. Si desea hacer coincidir las subclases, entoncesinstanceof
es necesario.Además, instanceof no coincidirá con un nulo, pero es seguro compararlo con un nulo. Por lo tanto, no tiene que comprobarlo nulo.
fuente
Depende si considera si una subclase de una clase dada es igual a su padre.
aquí usaría 'instanceof', porque quiero que se compare un Apellido con un Nombre de Familia
aquí usaría 'getClass', porque la clase ya dice que las dos instancias no son equivalentes.
fuente
instanceof funciona para instencias de la misma clase o subclases
ArryaList y RoleList son instancias de List
Mientras
getClass () == o.getClass () será verdadero solo si ambos objetos (this y o) pertenecen exactamente a la misma clase.
Entonces, dependiendo de lo que necesite comparar, podría usar uno u otro.
Si su lógica es: "Un objeto es igual a otro solo si ambos son de la misma clase", debe elegir "igual", que creo que es la mayoría de los casos.
fuente
Ambos métodos tienen sus problemas.
Si la subclase cambia la identidad, entonces necesita comparar sus clases reales. De lo contrario, viola la propiedad simétrica. Por ejemplo, diferentes tipos de
Person
s no deben considerarse equivalentes, incluso si tienen el mismo nombre.Sin embargo, algunas subclases no cambian de identidad y deben usarse
instanceof
. Por ejemplo, si tenemos un montón deShape
objetos inmutables , entonces unRectangle
con longitud y ancho de 1 debería ser igual a la unidadSquare
.En la práctica, creo que el primer caso es más probable que sea cierto. Por lo general, la subclasificación es una parte fundamental de su identidad y ser exactamente como su padre, excepto que puede hacer una pequeña cosa, no lo hace igual.
fuente
En realidad, instancia de comprobar dónde pertenece un objeto a alguna jerarquía o no. Ej: El objeto del automóvil pertenece a la clase Vehical. Entonces, "nueva instancia de Car () de Vehical" devuelve verdadero. Y "new Car (). GetClass (). Equals (Vehical.class)" devuelve falso, aunque el objeto Car pertenece a la clase Vehical pero está categorizado como un tipo separado.
fuente