Lorsque vous exécutez ceci:
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 réponse est:
true
false
Ce qui était assez renversant pour moi. J'aurais pensé que cela résulterait d'une erreur de compilation.
Pourquoi est-ce que je peux jeter null en Java, et pourquoi le convertit-il en upcast à une exception NullPointerException?
(En fait, je ne sais pas si c'est un "upcast", étant donné que je jette un nul)
Mis à part une question vraiment stupide lors d'une interview (personne ne la pose lors d'une interview, je vous prie), je ne vois aucune raison de throw null
. Peut-être que vous voulez être viré, mais c'est ... je veux dire, pourquoi quelqu'un d'autre throw null
?
Fait amusant IntelliJ IDEA 12 me dit que ma ligne, e instanceof NullPointerException
, Sera toujours fausse. Ce qui n'est pas vrai du tout.
Il semble que ce n’est pas que null
soit traité comme un NullPointerException
, mais que l’acte de tenter de throw null
lui-même jette un NullPointerException
.
En d'autres termes, throw
vérifie que son argument est non nul, et s'il est nul, il lance un NullPointerException
.
JLS 14.18 spécifie ce comportement:
Si l'évaluation de l'expression se termine normalement et génère une valeur null, une instance V 'de la classe NullPointerException est créée et renvoyée à la place de la valeur null. L'instruction de projection se termine alors brusquement, la raison en étant un jet de valeur V '.
pourquoi le retransmet-il à une exception NullPointerException?
Selon JLS 14.18 :
Une instruction de projection évalue d'abord l'expression. Si l'évaluation de l'expression se termine brusquement pour une raison quelconque, le lancer se termine alors brusquement pour cette raison. Si l'évaluation de l'expression se termine normalement, générant une valeur non nulle V, l'instruction de projection se termine brusquement, la raison en étant un jet de valeur V. Si l'évaluation de l'expression se termine normalement, produisant une valeur null, puis une instance V 'de la classe NullPointerException est créée et renvoyée à la place de null. L'instruction de lancement se termine alors abruptement, la raison en étant un jet de valeur V'.
Pourquoi puis-je insérer null dans Java?
Vous pouvez jeter des objets de type Throwable
et puisque null
est une référence valide pour Throwable
, le compilateur le permet.
C'est ce que Neal Gafter dit
Bien que null soit assignable à chaque type de référence, le type null n'est pas lui-même un type de référence. Notre intention était que l'exigence selon laquelle l'expression dans une instruction throw soit un type de référence soit supprimée de la troisième édition du JLS, mais cette modification n'a jamais été intégrée à la version publiée. Il s’agit donc d’un bogue du compilateur javac que j’ai introduit dans SE 5.
Il se comporte conformément aux JLS :
Si l'évaluation de l'expression se termine normalement et génère une valeur null, une instance V 'de la classe NullPointerException est créée et renvoyée à la place de null.
En pensant de cette façon, on comprend un peu mieux pourquoi cela fonctionne:
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);
}
Je ne sais pas avec certitude, mais je suppose que "jeter à zéro"; Est-ce que not fonctionne, et si on l'essaie, le programme lève une exception, et cette exception s'avère être (roulement de tambour) NullPointerException ...