Pregunta

Esta pregunta está específicamente relacionada con la anulación del método equals() para objetos con una gran cantidad de campos.En primer lugar, permítanme decirles que este objeto grande no se puede dividir en múltiples componentes sin violar los principios de OO, por lo que decirme "ninguna clase debería tener más de x campos" no ayudará.

Continuando, el problema se hizo realidad cuando olvidé marcar la igualdad en uno de los campos.Por lo tanto, mi método de igualdad era 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 (ni siquiera es el código que estoy usando), sino obtener información sobre si es una buena idea o no.

Ventajas:

  • Si se agrega un nuevo campo, se incluye automáticamente
  • El método es mucho más conciso que 30 declaraciones if.

Contras:

  • Si se agrega un nuevo campo, se incluye automáticamente; a veces esto no es deseable
  • Actuación:Esto tiene que ser más lento, no siento la necesidad de utilizar un generador de perfiles.
  • Incluir en la lista blanca ciertos campos para ignorar en la comparación es un poco feo

¿Alguna idea?

¿Fue útil?

Solución

Si desea incluirlos en la lista blanca por motivos de rendimiento, considere usar una anotación para indicar qué campos comparar.Además, esta implementación no funcionará si sus campos no tienen buenas implementaciones para equals().

PDSi sigues esta ruta por equals(), no olvides hacer algo similar para hashCode().

PPSConfío en que ya lo hayas considerado Generador de códigos hash y IgualesConstructor.

Otros consejos

¡Usa Eclipse, FFS!

Elimina el hashCode y los métodos iguales que tienes.

Haga clic derecho en el archivo.

Seleccione Fuente->Generar código hash y es igual...

¡Hecho!No más preocupaciones por 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 genere automáticamente.

Si opta por el enfoque de reflexión, EqualsBuilder sigue siendo su amigo:

 public boolean equals(Object obj) {
    return EqualsBuilder.reflectionEquals(this, obj);
 }

Aquí tienes una idea si estás preocupado:

1/ Olvidar actualizar su gran serie de declaraciones if para verificar la igualdad cuando agrega o 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 declaraciones if en su método equals().

b/ Tener una función única que contenga una lista de los campos (en una matriz de cadenas) y que comparará esa lista con la realidad (es decir, los campos reflejados).Lanzará una excepción si no coinciden.

c/ En su constructor para este objeto, tenga una llamada de ejecución única sincronizada 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 hará que sea inmediatamente obvio cuando ejecute su programa si no ha actualizado sus declaraciones if para que coincidan con los campos reflejados;luego corrige las declaraciones if y actualiza la lista de campos de (b) arriba.

La construcción posterior de objetos no realizará esta verificación y su método equals() se ejecutará a su máxima velocidad posible.

Por más que lo intenté, no he podido encontrar ningún problema real con este enfoque (pueden existir mentes más brillantes en StackOverflow): hay una verificación de condición adicional en cada construcción de objeto para el comportamiento de ejecución única, pero eso parece bastante menor.

Si se esfuerza lo suficiente, aún podría hacer que sus declaraciones if no estén en sintonía con su lista de campos y los campos reflejados, pero la excepción garantizará que su lista de campos coincida con los campos reflejados y usted solo se asegurará de actualizar las declaraciones if y el campo. lista al mismo tiempo.

Siempre puede anotar los campos que desea o no desea en su método de igualdad, lo que debería ser un cambio sencillo y directo.

Obviamente, el rendimiento está 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 utilicen más de lo que cree.

Además, hablando de mapas hash, tienes el mismo problema con el método hashCode.

Finalmente, ¿realmente necesitas comparar todos los campos para determinar la igualdad?

Tienes algunos errores en tu código.

  1. No puedes asumir que this y obj son la misma clase.De hecho, está explícitamente permitido obj ser cualquier otra clase.Podrías empezar con if ( ! obj instanceof myClass ) return false; sin embargo esto es todavía no es correcto porque obj podría ser una subclase de this con campos adicionales que podrían ser importantes.
  2. tienes que apoyar null valores para obj con un sencillo if ( obj == null ) return false;
  3. no puedes tratar null y cadena vacía como igual.En lugar de tratar null especialmente.La forma más sencilla aquí es empezar comparando Field.get(obj) == Field.get(this).Si ambos son iguales o ambos apuntan al mismo objeto, esto es rápido.(Nota:Esto también es una optimización, que necesita ya que es una rutina lenta). Si esto falla, puede usar la función rápida. if ( Field.get(obj) == null || Field.get(this) == null ) return false; para manejar casos donde exactamente uno es null.Finalmente puedes usar lo habitual. equals().
  4. no estas usando foundMismatch

Estoy de acuerdo con Hank en que [HashCodeBuilder][1] y [EqualsBuilder][2] es una mejor manera de hacerlo.Es fácil de mantener, no requiere mucho código repetitivo y evita todos estos problemas.

Podrías usar Anotaciones para excluir campos del cheque.

p.ej.

@IgnoreEquals
String fieldThatShouldNotBeCompared;

Y luego, por supuesto, verifica la presencia de la anotación en su método igual genérico.

Si tiene acceso a los nombres de los campos, ¿por qué no establece como estándar que los campos que no desea incluir siempre comiencen con "local" o "nochk" o algo así?

Luego, incluye en la lista negra todos los campos que comienzan con esto (el código no es tan feo entonces).

No dudo que sea un poco más lento.Debe decidir si desea intercambiar la facilidad de las actualizaciones con la velocidad de ejecución.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top