2011-04-14 15 views
20

Tengo un objeto de dirección para el que quiero crear un método igual. Podría haber hecho esto muy sencilla haciendo algo como lo siguiente (se ha reducido un poco):Java: Manera limpia de evitar NullPointerException en las comprobaciones equivalentes

public boolean equals(Object obj) 
{ 
    if (this == obj) 
     return true; 

    if (obj == null) 
     return false; 

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

    Address other = (Address) obj; 

    return this.getStreet().equals(other.getStreet()) 
     && this.getStreetNumber().equals(other.getStreetNumber()) 
     && this.getStreetLetter().equals(other.getStreetLetter()) 
     && this.getTown().equals(other.getTown()); 
} 

El problema es que algunos de estos podría ser nulo. En otras palabras, obtendré un NullPointerException si no hay una letra de calle en esta dirección.

¿Cómo puedo escribir esto de forma limpia teniendo en cuenta valores nulos?

+0

utilizando la anotación * @ NotNull * en todas partes sin duda ayuda. Lo mismo ocurre con el uso de cadenas vacías y matrices vacías, en lugar de cadenas nulas y matrices nulas para representar algo que está "vacío". Una cadena vacía es una cadena que no contiene ningún carácter. Una matriz vacía es una matriz hecha de elemento cero. "null" y NPE son extremadamente raros en nuestra base de código, donde la anotación * @ NotNull * se usa en cada clase que tenemos :) – SyntaxT3rr0r

+0

Además de eso, el concepto de "igualdad" sobre el objeto mutable no tiene mucho sentido . Haz que tus objetos sean inmutables. Prohibir nulo. Todo será más suave. – SyntaxT3rr0r

+0

¡Por supuesto, y lo haría si pudiera! El problema es que en este caso estas cosas * pueden * ser inexistentes. Por ejemplo, no todas las direcciones tienen una letra, por lo que debe ser nula. En cuanto a la inmutabilidad, estoy totalmente de acuerdo, pero desafortunadamente no es mi elección. Si dependiera de mí, lo sería. – Svish

Respuesta

15

Se puede utilizar un método de ayuda como

public static boolean isEqual(Object o1, Object o2) { 
    return o1 == o2 || (o1 != null && o1.equals(o2)); 
} 
+1

¡Agradable y conciso! Sin embargo, ¿no sería 'areEqual'? – Svish

+1

@Svish No necesariamente. _Es el Objeto o1 _equal_ para Objeto o2? –

+1

@Octavian, Buen punto ... algo en lo que pensar, jeje. – Svish

8

Se podría hacer lo siguiente:

public boolean equals(Object obj) 
{ 
    if (this == obj) { 
     return true; 
    } 

    if (obj == null) { 
     return false; 
    } 

    if (getClass() != obj.getClass()) { 
     return false; 
    } 

    Address other = (Address) obj; 

    return equals(this.getStreet(),other.getStreet()) 
     && equals(this.getStreetNumber(), other.getStreetNumber()) 
     && equals(this.getStreetLetter(), other.getStreetLetter()) 
     && equals(this.getTown(), other.getTown()); 
} 

private boolean equals(Object control, Object test) { 
    if(null == control) { 
     return null == test; 
    } 
    return control.equals(test); 
} 

Java 7 introducido soporte incorporado para este caso de uso con la clase java.util.Objects ver:

+0

@Jigar, ¿Por qué sería mejor? Creo que esto se ve mucho más limpio ... – Svish

+0

@Svish Se verá más limpio + sería óptimo también. –

+0

@Jigar, Personalmente creo que se ve más limpio como es. Pero, ¿por qué sería óptimo? No importa que lo mires, tienes 3 controles que posiblemente tengan que hacerse. Y si alguno de ellos pasa, detendrías la ejecución. ¿Hay algunas optimizaciones del compilador que no sé o algo así? – Svish

1

No hay una manera realmente limpia de hacerlo; la mejor opción es que tu IDE genere el código para ti. Eclipse puede hacerlo a través del menú contextual Source -> Generate hashCode() y equals().

0

Consideraría definir algunos de los métodos iguales como métodos de clase estáticos, como decir para los objetos de Street. De esta forma, nunca intente llamar al método .equals() en un nulo.

una función de ejemplo podría ser:

public static boolean equals(Object one, Object two) 

Además, es una buena práctica para poner los cheques como

if (obj == null) 
    return false; 

en el comienzo de una función.

+0

Sí, debo decir que echo de menos el método static 'Equals' que tienes sobre los objetos en C#. Sería útil en este caso. – Svish

7

Google Guava proporciona Objects.equal(Object, Object) que verifica la igualdad, teniendo en cuenta que ninguno de los parámetros podría ser nulo:

... 
return Objects.equal(this.getStreet(), other.getStreet()) 
    && Objects.equal(this.getStreetNumber(), other.getStreetNumber()) 
    && Objects.equal(this.getStreetLetter(), other.getStreetLetter()) 
    && Objects.equal(this.getTown(), other.getTown()); 

También vale la pena señalar que los objetos tienen otros métodos de ayuda para la implementación de hashCode() y toString().

3

tengo una clase de ayuda del inspector w/un método estático:

public static boolean isEquals(final Object o1, final Object o2) { 
     return o1 == null ? o2 == null : o1.equals(o2); 
} 

así, en el método equals,

return Checker.isEquals(this.getStreet(), other.getStreet()) 
     && Checker.isEquals(this.getStreetNumber(), other.getStreetNumber()) 
     && Checker.isEquals(this.getStreetLetter(), other.getStreetLetter()) 
     && Checker.isEquals(this.getTown(), other.getTown()); 
+0

Llamo a mi clase "Checker" "clase pública NullSafe" en su lugar. –

0

Apache Commons Lang proporciona la clase de ayuda EqualsBuilder para comparar la igualdad. También hay uno para códigos hash.

return new EqualsBuilder() 
.append(this.getStreet(), other.getStreet()) 
.append(this.getStreetNumber(), other.getStreetNumber() 
.append(this.getStreetLetter(), other.getStreetLetter()) 
.append(this.getTown(), other.getTown())).isEquals(); 
Cuestiones relacionadas