Evitando graciosamente NullPointerException en Java


Considere esta línea:

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

Obviamente esta línea es un error potencial, el atributo podría ser null y obtendremos un NullPointerException. Así que necesitamos refactorizarlo 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 la segunda es clara en la intención, pero detallada.

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

Author: Jon Seigel, 2009-06-08

9 answers

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 creo que es lo suficientemente legible para que te acostumbres muy fácilmente

 27
Author: victor hugo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-08 08:58:07

En la segunda opción, puedes aprovechar el cortocircuito &&:

String attr = object.getAttribute("someAttr");
if (attr != null && attr.equals("true")) { // ....
 17
Author: laalto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-08 08:55:45

Hay ciertas situaciones en las que el enfoque conciso se siente mal 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? Impensable! Excepto que es básicamente mejor que las alternativas, cuando reconoces el patrón particular.

Este patrón es similar - es tan común en Java que esperaría que cualquier desarrollador razonablemente experimentado lo reconociera. El resultado es agradable conciso. (Curiosamente, a veces veo código de C# que usa el mismo modismo, innecesariamente - el operador de igualdad funciona bien con cadenas en C#.)

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

 2
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-08 09:02:57

Me gusta la opción 1 y yo dirí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.

 1
Author: willcodejavaforfood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-08 08:53:05

Siempre aspira a un código más corto, dado que ambos son funcionalmente equivalentes. Especialmente en casos como este donde la legibilidad no se sacrifica.

 1
Author: Marko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-08 08:56:58

Util.isEmpty(string) - devuelve string == null || string.trim().isEmpty() Util.notNull(string) devuelve "" si string == null, cadena de lo contrario. Util.isNotEmpty(string) vuelve ! Util.isEmpty(string)

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

 0
Author: alamar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-08 08:55:23

Es una muy buena pregunta. Normalmente uso el no agraciado:

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

(y no lo usaré más)

 0
Author: alexmeia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-11 23:07:08

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, así que en get(0).get ("group_c80") acuerdos de excepción de puntero nulo. Pero lo manejé a través del siguiente código:

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
Author: m s,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-05 18:33:33

Aquí está mi enfoque, necesita una clase PropertyUtil, pero solo se escribe 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 Lista, que rechazaría Objeto:

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

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

 0
Author: juanmf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-29 16:00:06