¿Por qué puedo lanzar null en Java?


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

Que fue bastante impresionante para mí. Yo habría pensado que esto red un error en tiempo de compilación.

¿Por qué puedo lanzar null en Java, y por qué lo transmite a una NullPointerException?

(En realidad, no se si es un "upcast", dado que estoy lanzando null)

Aparte de una pregunta de entrevista realmente estúpida (por favor, que nadie haga esto en una entrevista) No puedo ver ninguna razón para throw null. Tal vez quieras que te despidan, pero eso es... Quiero decir, ¿por qué otra cosa alguien throw null?

Dato curioso IntelliJ IDEA 12 me dice que mi línea, e instanceof NullPointerException, siempre será falsa. Lo cual no es cierto en absoluto.

Author: Peter Mortensen, 2013-07-10

7 answers

Parece Que no es que null es tratado como un NullPointerException, sino que el acto de intentar throw null lanza un NullPointerException.

En otras palabras, throw comprueba que su argumento es nonnull, y si es null, lanza un NullPointerException.

JLS 14.18 especifica este comportamiento:

Si la evaluación de la expresión se completa normalmente, produciendo un valor null, entonces se crea una instancia V' de la clase NullPointerException y se lanza en lugar de null. El la sentencia throw luego se completa abruptamente, la razón es un throw con valor V'.

 395
Author: Louis Wasserman,
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
2013-07-10 17:24:11

¿Por qué lo transmite a una excepción NullPointerException?

Según JLS 14.18:

Una sentencia throw primero evalúa la expresión. Si la evaluación de la expresión se completa abruptamente por alguna razón, entonces el tiro se completa abruptamente por esa razón. Si la evaluación de la expresión se completa normalmente, produciendo un valor no nulo V, entonces la instrucción throw se completa abruptamente, la razón es un throw con valor V. Si la evaluación de la expresión se completa de forma La expresión se completa normalmente, produciendo un valor null, luego se crea una instancia V' de la clase NullPointerException y se lanza en lugar de null. La sentencia throw luego se completa abruptamente, la razón es un throw con valor V'.

¿Por qué puedo lanzar null en java ?

Puede lanzar objetos de tipo Throwable y como null es una referencia válida para Throwable, el compilador lo permite.

Esto es lo que Neal Gafter dice

Aunque null es asignable a cada tipo de referencia, el tipo de null no es en sí mismo un tipo de referencia. Nuestra intención era que el requisito de que la expresión en una sentencia throw fuera un tipo de referencia se eliminara de la tercera edición de la 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.

 93
Author: NINCOMPOOP,
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
2013-07-11 08:30:51

Se comporta de conformidad con el JLS :

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

 21
Author: assylias,
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
2013-07-10 17:22:56

Pensar en ello de esta manera hace que sea un poco más obvio en cuanto a 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);
}
 18
Author: Nick Gotch,
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
2013-07-10 22:19:14

No lo sé con seguridad, pero supongo que "lanzar null"; no funciona, y intentarlo hace que el programa lance una excepción, y esa excepción pasa a ser (redoble de tambor) NullPointerException...

 13
Author: ajb,
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
2013-07-10 17:18:30

null puede ser lanzado a cualquier cosa*, incluyendo una Excepción. Del mismo modo que podría devolver null si su firma de método especifica que debe devolver una excepción (o de hecho una cadena o clase Person), puede lanzarla.

*Excluyendo tipos primitivos.

 -3
Author: Marc,
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
2013-07-12 15:12:29

Bharal...It parece un error del compilador javac. Creo que fue introducido en SE 5. Null se puede asignar a cualquier tipo de referencia. Sin embargo, "el tipo de null" no es en sí mismo un tipo de referencia. El programa lo compila porque null puede simplemente convertir en Excepción. Y además throw busca referencia de objeto después de la declaración y como null puede funcionar como referencia de objeto muestra el resultado.

El documento de JLS sobre throw como:

" Una instrucción throw evalúa primero Expresion. Si la evaluación de la Expresión completa abruptamente por alguna razón, entonces el tiro completa abruptamente por esa razón. If evaluación de la Expresión completa normalmente, produciendo un valor no nulo V, luego el tiro la declaración se completa abruptamente, la razón es un tiro con valor V. Si la evaluación de la expresión se completa normalmente, se produce un valor nulo valor, luego se crea una instancia V ' de la clase NullPointerException y lanzado en lugar de nulo. Tiro la declaración se completa abruptamente, la razón es un tiro con valor V'."

 -3
Author: techhunter,
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
2014-07-26 10:43:47