Why can I throw null in Java?
运行时:
1 2 3 4 5 6 7 8 9 10 11 | 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); } } } |
回应是:
1 2 | true false |
这对我来说相当惊人。 我原本以为这会造成编译时错误。
为什么我可以在Java中抛出null,为什么要将它转换为NullPointerException呢?
(实际上,我不知道它是否是"向上",因为我扔的是null)
除了一个非常愚蠢的面试问题(请不要在面试中问这个)我看不出
有趣的事实IntelliJ IDEA 12告诉我,我的行
看起来并不是
换句话说,
JLS 14.18指定了这种行为:
If evaluation of the Expression completes normally, producing a null value, then an instance V' of class NullPointerException is created and thrown instead of null. The throw statement then completes abruptly, the reason being a throw with value V'.
为什么它会将它转发为NullPointerException?
根据JLS 14.18:
A throw statement first evaluates the Expression. If the evaluation of the Expression completes abruptly for some reason, then the throw completes abruptly for that reason. If evaluation of the Expression completes normally, producing a non- null value V, then the throw statement completes abruptly, the reason being a throw with value V. If evaluation of the Expression completes normally, producing a null value, then an instance V’ of class NullPointerException is created and thrown instead of null. The throw statement then completes abruptly, the reason being a throw with value V’.
为什么我可以在java中抛出null?
您可以抛出
这就是Neal Gafter所说的
尽管null可分配给每个引用类型,但null的类型本身不是引用类型。我们的意图是要求将throw语句中的表达式作为引用类型从JLS的第三版中删除,但该更改实际上从未实际进入已发布的版本。因此,这是我在SE 5中介绍的javac编译器错误。
它的行为符合JLS:
If evaluation of the Expression completes normally, producing a null value, then an instance V' of class NullPointerException is created and thrown instead of null.
以这种方式思考它会使其更加明显:
1 2 3 4 5 6 7 8 9 10 | 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); } |
不确定,但我猜"扔掉";不起作用,并尝试它会导致程序抛出异常,并且该异常恰好是(鼓滚动)NullPointerException ...
null可以转换为任何*,包括异常。就像你的方法签名指定你应该返回一个Exception(或者确实是一个字符串或Person类)一样,你可以返回null,你可以抛出它。
*不包括原始类型。
bharal ...它看起来像一个javac编译器bug。我认为它是在SE 5中引入的。
Null可以分配给任何引用类型。但是,"null类型"本身不是引用类型。程序编译它,因为null可以简单地转换为Exception。
此外,throw会在声明后查找对象引用,并且null可以作为对象引用,它会显示结果。
关于throw的JLS文档:
"A throw statement first evaluates the Expression. If the evaluation
of the Expression completes abruptly for some reason, then the throw
completes abruptly for that reason. If evaluation of the Expression
completes normally, producing a non-null value V, then the throw
statement completes abruptly, the reason being a throw with value V.
If evaluation of the Expression completes normally, producing a null
value, then an instance V’ of class NullPointerException is created
and thrown instead of null. The throw statement then completes
abruptly, the reason being a throw with value V’."