java - ¿Para qué tipo de igualdad es igual el método de Apache Commons ObjectUtils?
equals apache-commons (3)
¿Tengo razón en preocuparme y querer evitar el uso de ObjectUtils.equals () siempre que sea posible?
No. Lo que debe considerar es igual a sus necesidades. Y querer considerar dos nulos iguales y cualquier no nulo no igual a un nulo sin tener que lidiar con NullPointerExceptions es un requisito muy, muy común (por ejemplo, cuando desea disparar eventos de cambio de valor desde un definidor).
En realidad, es cómo debería funcionar equals()
en general, y, por lo general, se implementa la mitad de ese comportamiento (la documentación API de Object.equals()
indica que "Para cualquier valor de referencia no nulo x
, x.equals(null)
debe devolver falso. "): el hecho de que no funcione al revés se debe principalmente a restricciones técnicas (el lenguaje se diseñó sin que el envío múltiple sea más sencillo).
Siempre he entendido que hay dos tipos de igualdad en Java,
- igualdad de valor : utiliza el método
.equals()
para probar que dos objetos implementan una relación de equivalencia en referencias de objetos no nulos. - igualdad de referencia : utiliza el operador
==
para probar que dos tipos primitivos o ubicaciones de memoria son iguales.
Las siguientes páginas describen estos fundamentos del lenguaje con más detalle.
- Wikibooks Programación Java: Programación Java / Comparación de Objetos
- Preguntas frecuentes sobre xyzws Java EE: ¿Cuáles son las diferencias entre el operador de igualdad y el método equals?
- API de la plataforma Java: Javadoc para Object.equals ()
- Especificación del lenguaje Java: Operadores de igualdad
Lo que ninguno de estos enlaces especifica explícitamente es lo que debería ocurrir si se comparan dos referencias de objetos null
para la igualdad de valores. La suposición implícita es que se debe lanzar una NullPointerException
pero esto no es lo que hace el método ObjectUtils.equals() , que podría considerarse un método de utilidad de mejores prácticas .
Lo que me preocupa es que Apache Commons parece haber introducido efectivamente una tercera medida de igualdad en Java por la puerta de atrás y que el ya confuso estado de cosas podría haberse vuelto mucho más complejo. Lo llamo una tercera medida de igualdad porque intenta probar la igualdad de valores y cuando esto falla, vuelve a probar la igualdad de referencia. La prueba de igualdad de Apache Commons tiene muchas similitudes con la igualdad de valores y la igualdad de referencia, pero también es claramente diferente.
¿Tengo razón en preocuparme y querer evitar el uso de ObjectUtils.equals()
siempre que sea posible?
¿Hay ObjectUtils.equals()
argumento para afirmar que ObjectUtils.equals()
proporciona una unión útil de las otras dos medidas de igualdad?
Respuesta elegida
No parece haber una opinión de consenso sobre esta pregunta, pero decidí marcar la de Bozho como correcta porque me llamó mucho la atención sobre lo que ahora veo como el mayor problema con los cheques sin riesgo equivalentes a los seguros. Todos deberíamos estar escribiendo un código rápido de fallas que aborde la causa raíz de por qué dos objetos nulos se comparan por la igualdad de valores en lugar de tratar de barrer el problema debajo de la alfombra.
Aquí está el código de ObjectUtils.equals(..)
:
public static boolean equals(Object object1, Object object2) {
if (object1 == object2) {
return true;
}
if ((object1 == null) || (object2 == null)) {
return false;
}
return object1.equals(object2);
}
Los documentos de ObjecUtils establecen claramente que los objetos pasados pueden ser nulos.
Ahora, en el caso de si se debe devolver true
si compara dos null
. En mi opinión, no, porque:
- cuando compares dos objetos, probablemente vas a hacer algo con ellos más adelante. Esto conducirá a una
NullPointerException
- pasar dos
null
para comparar significa que obtuvieron de algún lugar en lugar de objetos "reales", tal vez debido a algún problema. En ese caso, compararlos solo es incorrecto: el flujo del programa debería haberse detenido antes de eso. - En una biblioteca personalizada que estamos usando aquí, tenemos un método llamado
equalOrBothNull()
, que difiere del métodoequals
en esta utilidad en la comparación nula.
Si le preocupa esto, entonces puede 1) no usar este método 2) escribir el suyo propio para envolverlo
public class MyObjectUtils {
public static boolean equals(Object obj1, Object obj2) {
return obj1 != null && obj2 != null && ObjectUtils.equals(obj1, obj2);
}
}
A mí me parece extraño permitir que null sea igual a null, pero esto no parece ser un gran problema. En su mayor parte, no esperaría que mi aplicación llegara a las rutas de código que involucran pruebas de igualdad si uno o más objetos son nulos.