¿Por qué puedo arrojar nulo en Java? [duplicar]

Resuelto bharal asked hace 11 años • 7 respuestas

Al ejecutar esto:

public class WhatTheShoot {

    public static void main(String args[]){
        try {
            throw null;
        } catch (Exception e){
            System.out.println(e instanceof NullPointerException);
            System.out.println(e instanceof FileNotFoundException);
        }
    }
}

La respuesta es:

true  
false

Lo cual fue bastante sorprendente para mí. Pensé que esto generaría un error en tiempo de compilación.

¿Por qué puedo arrojar un valor nulo en Java y por qué lo convierte en una excepción NullPointerException?

(En realidad, no sé si es un "upcast", dado que estoy arrojando nulo)

Aparte de una pregunta de entrevista realmente estúpida (por favor, que nadie haga esto en una entrevista), no veo ninguna razón para hacerlo throw null. Tal vez quieras que te despidan, pero eso es... Quiero decir, ¿por qué si no querría alguien throw null?

Dato curioso: IntelliJ IDEA 12 me dice que mi línea e instanceof NullPointerExceptionsiempre será falsa. Lo cual no es del todo cierto.

bharal avatar Jul 11 '13 00:07 bharal
Aceptado

Parece que no es que nullse trate como un NullPointerException, sino que el acto de intentarlo throw null arroja un NullPointerException.

En otras palabras, throwcomprueba que su argumento no sea nulo y, si es nulo, arroja un archivo NullPointerException.

JLS 14.18 especifica este comportamiento:

Si la evaluación de la expresión se completa normalmente y produce un valor nulo, entonces se crea y se lanza una instancia V' de la clase NullPointerException en lugar de nula. La declaración de lanzamiento luego se completa abruptamente, siendo el motivo un lanzamiento con valor V'.

Louis Wasserman avatar Jul 10 '2013 17:07 Louis Wasserman

¿Por qué lo convierte en NullPointerException?

Según JLS 14.18 :

Una declaración de lanzamiento primero evalúa la expresión. Si la evaluación de la Expresión se completa abruptamente por algún motivo, entonces el lanzamiento se completa abruptamente por ese motivo. Si la evaluación de la Expresión se completa normalmente, produciendo un valor V no nulo, entonces la declaración de lanzamiento se completa abruptamente, la razón es un lanzamiento con valor V. Si la evaluación de la Expresión se completa normalmente, produciendo un valor nulo, entonces se crea una instancia V' de la clase NullPointerException se crea y se lanza en lugar de nulo. La declaración de lanzamiento luego se completa abruptamente, siendo el motivo un lanzamiento con valor V'.

¿Por qué puedo arrojar nulo en Java?

Puedes lanzar objetos de tipo Throwabley como nulles una referencia válida para Throwable, el compilador lo permite.

Esto es lo que dice Neal Gafter ( archivado )

Aunque nulo se puede asignar a cada tipo de referencia, el tipo nulo no es en sí mismo un tipo de referencia. Nuestra intención era eliminar el requisito de que la expresión en una declaración de lanzamiento fuera un tipo de referencia de la tercera edición de JLS, pero ese cambio nunca llegó a la versión publicada. Por lo tanto, este es un error del compilador javac que introduje en SE 5.

AllTooSir avatar Jul 10 '2013 17:07 AllTooSir

Se comporta de conformidad con el JLS :

Si la evaluación de la expresión se completa normalmente y produce un valor nulo, entonces se crea y se lanza una instancia V' de la clase NullPointerException en lugar de nula.

assylias avatar Jul 10 '2013 17:07 assylias

Pensarlo de esta manera hace que sea un poco más obvio por qué funciona esto:

try {
    Exception foo = null;
    if(false) {
        foo = new FileNotFoundException();
    } // Oops, forgot to set foo for the true case..
    throw foo;
} catch (Exception e){
    System.out.println(e instanceof NullPointerException);
    System.out.println(e instanceof FileNotFoundException);
}
Nick Gotch avatar Jul 10 '2013 22:07 Nick Gotch