que - Java es igual a(): para reflejar o no para reflejar
que diferencias existen entre el lenguaje de programacion c++ y java (9)
Esta pregunta está específicamente relacionada con anular el método equals () para objetos con una gran cantidad de campos. En primer lugar, permítanme decir que este gran objeto no se puede dividir en varios componentes sin violar los principios de OO, por lo que decirme "ninguna clase debe tener más de x campos" no ayudará.
Continuando, el problema se concretó cuando olvidé verificar uno de los campos para la igualdad. Por lo tanto, mi método equals fue incorrecto. Entonces pensé en usar la reflexión:
--code removed because it was too distracting--
El propósito de esta publicación no es necesariamente refactorizar el código (este ni siquiera es el código que estoy usando), sino más bien obtener una opinión sobre si esta es una buena idea o no.
Pros:
- Si se agrega un nuevo campo, se incluye automáticamente
- El método es mucho más escueto que 30 si las declaraciones
Contras:
- Si se agrega un nuevo campo, se incluye automáticamente, a veces esto es indeseable
- Rendimiento: Esto tiene que ser más lento, no siento la necesidad de crear un generador de perfiles
- Incluir en la lista blanca ciertos campos para ignorar en la comparación es un poco feo
¿Alguna idea?
Si tiene acceso a los nombres de los campos, ¿por qué no establece como estándar que los campos que no desea incluir comiencen siempre con "local" o "nochk" o algo por el estilo?
Luego, coloca en la lista negra todos los campos que comienzan con esto (el código no es tan feo entonces).
No lo dudo, es un poco más lento. Debe decidir si desea intercambiar la facilidad de actualización con la velocidad de ejecución.
Aquí hay un pensamiento si te preocupa:
1 / Olvidarse de actualizar su gran serie de declaraciones if para verificar la igualdad cuando agrega / elimina un campo.
2 / El rendimiento de hacer esto en el método equals ().
Pruebe lo siguiente:
a / Vuelva a utilizar la secuencia larga de sentencias if en su método equals ().
b / Tener una sola función que contiene una lista de los campos (en una matriz de Cadenas) y que verificará esa lista contra la realidad (es decir, los campos reflejados). Lanzará una excepción si no coinciden.
c / En su constructor para este objeto, tenga una llamada sincronizada de ejecución una vez a esta función (similar a un patrón singleton). En otras palabras, si este es el primer objeto construido por esta clase, llame a la función de verificación descrita en (b) arriba.
La excepción lo hará inmediatamente obvio cuando ejecute su programa si no ha actualizado sus declaraciones if para que coincidan con los campos reflejados; luego corrige los enunciados if y actualiza la lista de campos de (b) anterior.
La construcción posterior de objetos no hará esta comprobación y su método equals () se ejecutará a su máxima velocidad posible.
Por más que lo intente, no he podido encontrar ningún problema real con este enfoque (pueden existir mentes más grandes en ): hay una verificación de condición adicional en cada construcción de objeto para el comportamiento de ejecutar una vez, pero eso parece bastante menor.
Si lo intentas lo suficiente, aún podrías desordenar tus declaraciones if con tu lista de campos y campos reflejados, pero la excepción asegurará que tu lista de campos coincida con los campos reflejados y solo asegúrate de actualizar los enunciados if y el campo lista al mismo tiempo.
Si sigues el enfoque de reflexión, EqualsBuilder sigue siendo tu amigo:
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}
Tienes algunos errores en tu código.
- No puede suponer que
this
yobj
son de la misma clase. De hecho, está permitido explícitamente queobj
sea cualquier otra clase. Puede comenzar conif ( ! obj instanceof myClass ) return false;
sin embargo, esto todavía no es correcto porqueobj
podría ser una subclase dethis
con campos adicionales que podrían ser importantes. - Debe admitir valores
null
paraobj
con un simpleif ( obj == null ) return false;
- No puede tratar cadenas
null
y vacías como iguales. En lugar de tratarnull
especialmente. La forma más simple aquí es comenzar comparandoField.get(obj) == Field.get(this)
. Si ambos son iguales o ambos apuntan al mismo objeto, esto es rápido. (Nota: Esta también es una optimización, que necesita, ya que esta es una rutina lenta.) Si esto falla, puede usar el ayunoif ( Field.get(obj) == null || Field.get(this) == null ) return false;
para manejar casos donde exactamente uno esnull
. Finalmente puede usar losequals()
usualesequals()
. - No estás usando
foundMismatch
Estoy de acuerdo con Hank en que [HashCodeBuilder][1]
y [EqualsBuilder][2]
es una mejor forma de hacerlo. Es fácil de mantener, no muchos códigos repetitivos, y evita todos estos problemas.
¡Usa Eclipse, FFS!
Elimina el hashCode y es igual a los métodos que tienes.
Haga clic derecho en el archivo.
Seleccione Fuente-> Generar hashcode y es igual a ...
¡Hecho! No más preocupaciones sobre la reflexión.
Repita para cada campo agregado, solo use la vista de esquema para eliminar sus dos métodos, y luego deje que Eclipse los autogenere.
Puede usar Anotaciones para excluir campos del cheque
p.ej
@IgnoreEquals
String fieldThatShouldNotBeCompared;
Y luego, por supuesto, verifica la presencia de la anotación en tu método genérico igual.
Eche un vistazo a org.apache.commons.EqualsBuilder:
Si desea incluir en la lista blanca por razones de rendimiento, considere usar una anotación para indicar qué campos comparar. Además, esta implementación no funcionará si tus campos no tienen buenas implementaciones para equals()
.
PD: si hashCode()
esta ruta para equals()
, no olvide hacer algo similar para hashCode()
.
PPS Confío en que ya haya considerado HashCodeBuilder e EqualsBuilder .
Siempre puede anotar los campos que desea / no quiere en su método equals, que debería ser un cambio sencillo y directo.
El rendimiento está obviamente relacionado con la frecuencia con la que se compara realmente el objeto, pero muchos marcos utilizan mapas hash, por lo que es posible que sus iguales se estén utilizando más de lo que cree.
Además, hablando de mapas hash, tiene el mismo problema con el método hashCode.
Finalmente, ¿realmente necesita comparar todos los campos para la igualdad?