2009-06-08 13 views
22

considerar esta línea:evitando con Gracia NullPointerException en Java

if (object.getAttribute("someAttr").equals("true")) { // .... 

Obviamente esta línea es un error potencial, el atributo podría ser null y vamos a conseguir un NullPointerException. Así que tenemos que refactorizar a una de dos opciones:

Primera opción:

if ("true".equals(object.getAttribute("someAttr"))) { // .... 

Segunda opción:

String attr = object.getAttribute("someAttr"); 
if (attr != null) { 
    if (attr.equals("true")) { // .... 

La primera opción es difícil de leer, pero más concisa , mientras que el segundo es claro en su intención, pero detallado.

¿Qué opción prefiere en términos de legibilidad?

Respuesta

27

Siempre he usado

if ("true".equals(object.getAttribute("someAttr"))) { // .... 

porque aunque es un poco más difícil de leer es mucho menos detallado y yo creo que es lo suficientemente legible para que se acostumbre a ella muy fácilmente

+3

Ni siquiera creo que esto es más difícil leer. –

1

me gusta opción 1 y yo argumentaría que es lo suficientemente legible.

La opción 3, por cierto, sería introducir un método getAttribute que toma un valor predeterminado como parámetro.

+0

Esta pregunta es sobre el bloque 'si', así que sobre su opción 3: "No siempre se puede confiar en que el método nunca devolverá un valor nulo –

+0

Por supuesto, puede asegurarse de que nunca devuelve un valor predeterminado nulo. – willcodejavaforfood

+0

Opción 3 consistiría en mover el manejo de errores y las comprobaciones nulas en un método según DRY. – willcodejavaforfood

0

Util.isEmpty(string) - devuelve string == null || string.trim().isEmpty() Util.notNull(string) devuelve "" si string == null, cadena en caso contrario. Util.isNotEmpty(string) regresa! Util.isEmpty(string)

Y tenemos una convención que para cadenas, Util.isEmpty(string) significa semánticamente cierto y Util.isNotEmpty(string) significa semánticamente falso.

17

En la segunda opción, se puede tomar ventaja de un cortocircuito &&:

String attr = object.getAttribute("someAttr"); 
if (attr != null && attr.equals("true")) { // .... 
+1

De hecho, puede, pero es la optimización favorecida a la lectura, siempre una mala idea. –

+6

Huh, favorece la optimización? Creo, por el contrario, que esto es un poco más legible que la opción 1. – Jonik

+1

Sí, los problemas de estilo no tienen respuestas definitivas. Es lo que has acostumbrado. Personalmente, me he acostumbrado a este estilo ya que también me afecta. ks en muchos otros lenguajes que derivan sintaxis de C/C++. Y si su organización/proyecto tiene una convención de código, siga sus recomendaciones. – laalto

1

siempre aspiran para el código más corto, dado que ambos son equivalentes functionaly. Especialmente en casos como este donde la legibilidad no se sacrifica.

2

Existen ciertas situaciones en las que el enfoque conciso parece incorrecto para empezar, pero efectivamente se convierte en idiomático. Este es uno de ellos; el otro es algo así como:

String line; 
while ((line = bufferedReader.readLine()) != null) { 
    // Use line 
} 

¿Efectos secundarios en una condición? ¡Inconcebible! Excepto que es básicamente más agradable que las alternativas, cuando reconoces el patrón en particular.

Este patrón es similar, es tan común en Java que esperaría que cualquier desarrollador razonablemente experimentado lo reconozca. El resultado es agradablemente conciso. (De manera divertida, a veces veo el código C# que usa el mismo idioma innecesariamente; el operador de igualdad funciona bien con cadenas en C#.)

En pocas palabras: utilice la primera versión y familiarícese con ella.

0

Es una muy buena pregunta. lo general el uso de la no grácil:

if (object.getAttribute("someAttr") != null && object.getAttribute("someAttr").equals("true")) { // .... 

(y no voy a usarlo nunca más)

+4

¡Qué bueno! getAttribute() en realidad tiene efectos secundarios? Algunas veces lo está ejecutando una vez, a veces lo está ejecutando dos veces –

+0

Podría escribir esto en la pregunta "Errores comunes de programación" que he visto aquí –

+0

Gracias por los comentarios. sabía que no era bueno, estoy aquí para aprender cosas como esta. Una pregunta más: ¿cuál es el problema con este enfoque si getAttribute() es solo un método getter estándar, y por lo tanto no tiene efectos secundarios? – alexmeia

0

tengo otra respuesta;

List<Map<String, Object>> group = jjDatabase.separateRow(db.Select("SELECT * FROM access_user_group WHERE user_id=1 ;")); 

no hay "group_c80" como columna en 'access_user_group' en mi base de datos, por lo que en get (0) .get ("group_c80") acuerdos excepción de puntero nulo. Pero lo manejé través de código de abajo:

for (int j = 1; j < 100; j++) { 
        String rulId="0";//defult value,to privent null pointer exeption in group_c 
        try { 
         rulId = group.get(0).get("group_c" + j)).toString(); 
        } catch (Exception ex) { 
         ServerLog.Print("Handeled error in database for " + "group_c" + (j < 10 ? "0" + j : j) +"This error handeled and mot efect in program"); 
         rulId = "0"; 
        }} 
0

Aquí está mi enfoque, necesita una clase PropertyUtil sin embargo, pero su único escrito una vez:

/** 
* Generic method to encapsulate type casting and preventing nullPointers. 
* 
* @param <T>   The Type expected from the result value. 
* @param o   The object to cast. 
* @param typedDefault The default value, should be of Type T. 
* 
* @return Type casted o, of default. 
*/ 
public static <T> T getOrDefault (Object o, T typedDefault) { 
    if (null == o) { 
     return typedDefault; 
    } 
    return (T) o; 
} 

El código de cliente puede hacer esto:

PropertyUtil.getOrDefault(obj.getAttribute("someAttr"), "").equals("true"); 

o, para una lista:

PropertyUtil.getOrDefault(
    genericObjectMap.get(MY_LIST_KEY), Collections.EMPTY_LIST 
).contains(element); 

O a un consumidor de la lista, que rechazarían objeto:

consumeOnlyList(
    PropertyUtil.getOrDefault(
     enericObjectMap.get(MY_LIST_KEY), Collections.EMPTY_LIST 
    ) 
) 

El valor predeterminado puede ser un impl del patrón de objeto nulo https://en.wikipedia.org/wiki/Null_Object_pattern

Cuestiones relacionadas